diff --git a/CMakeLists.txt b/CMakeLists.txt index 01f622c0..8f795d1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,11 @@ foreach( p LIB BIN INCLUDE CMAKE DOC) endif() endforeach() +if(WIN32) option(ENABLE_SHARED "Enable Shared Libraries" ON) +else(WIN32) +option(ENABLE_SHARED "Enable Shared Libraries" ON) +endif(WIN32) if ( ENABLE_SHARED ) set( DO_SHARED SHARED ) @@ -58,6 +62,8 @@ include( configure.cmake ) include_directories( "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" ) # implement find library stuff... +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + add_definitions( -DPACKAGE="CTL" -DVERSION="${CTL_VERSION}" ) add_subdirectory(doc) add_subdirectory(lib) diff --git a/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt b/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt index e396ec5a..5185592a 100644 --- a/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt +++ b/OpenEXR_CTL/exr_ctl_exr/CMakeLists.txt @@ -1,4 +1,8 @@ +if(WIN32) + add_definitions( -DOPENEXR_DLL ) +endif(WIN32) + include_directories( ${OpenEXR_INCLUDE_DIRS} ) link_directories( ${OpenEXR_LIBRARY_DIRS} ) diff --git a/OpenEXR_CTL/exrdpx/CMakeLists.txt b/OpenEXR_CTL/exrdpx/CMakeLists.txt index 50bd116e..ef1f0dd4 100644 --- a/OpenEXR_CTL/exrdpx/CMakeLists.txt +++ b/OpenEXR_CTL/exrdpx/CMakeLists.txt @@ -1,4 +1,8 @@ +if(WIN32) + add_definitions( -DOPENEXR_DLL ) +endif(WIN32) + include_directories( ${OpenEXR_INCLUDE_DIRS} ) link_directories( ${OpenEXR_LIBRARY_DIRS} ) diff --git a/cmake/modules/FindIlmBase.cmake b/cmake/modules/FindIlmBase.cmake index a51cdd8b..89953836 100644 --- a/cmake/modules/FindIlmBase.cmake +++ b/cmake/modules/FindIlmBase.cmake @@ -1,10 +1,10 @@ # -# A simple cmake find module for IlmBase +# A simple cmake find module for Imath # find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_ILMBASE QUIET IlmBase) + pkg_check_modules(PC_ILMBASE QUIET Imath) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -23,10 +23,12 @@ if(PC_ILMBASE_FOUND) set(IlmBase_LIBRARY_DIRS ${PC_ILMBASE_LIBRARY_DIRS}) set(IlmBase_LDFLAGS ${PC_ILMBASE_LDFLAGS_OTHER}) if("${_IlmBase_HINT_INCLUDE}" STREQUAL "") - set(_IlmBase_HINT_INCLUDE ${PC_ILMBASE_INCLUDEDIR} ${PC_ILMBASE_INCLUDE_DIRS}) - set(_IlmBase_HINT_LIB ${PC_ILMBASE_LIBDIR} ${PC_ILMBASE_LIBRARY_DIRS}) + set(_IlmBase_HINT_INCLUDE ${CMAKE_PREFIX_PATH}/include ) + set(_IlmBase_HINT_LIB ${CMAKE_PREFIX_PATH}/lib ${CMAKE_PREFIX_PATH}/lib64 ) endif() else() + set(_IlmBase_HINT_INCLUDE ${CMAKE_PREFIX_PATH}/include ) + set(_IlmBase_HINT_LIB ${CMAKE_PREFIX_PATH}/lib ${CMAKE_PREFIX_PATH}/lib64 ) if(UNIX) set(IlmBase_CFLAGS "-pthread") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -36,29 +38,29 @@ else() endif() endif() -find_path(IlmBase_INCLUDE_DIR IlmBaseConfig.h HINTS ${_IlmBase_HINT_INCLUDE} PATH_SUFFIXES OpenEXR ) -if(IlmBase_INCLUDE_DIR AND EXISTS "${IlmBase_INCLUDE_DIR}/IlmBaseConfig.h") - set(IlmBase_VERSION ${PC_ILMBASE_VERSION}) +find_path(IlmBase_INCLUDE_DIR ImathConfig.h HINTS ${_IlmBase_HINT_INCLUDE} PATH_SUFFIXES Imath ) +if(IlmBase_INCLUDE_DIR AND EXISTS "${IlmBase_INCLUDE_DIR}/ImathConfig.h") + #set(IlmBase_VERSION ${PC_ILMBASE_VERSION}) if("${IlmBase_VERSION}" STREQUAL "") - file(STRINGS "${IlmBase_INCLUDE_DIR}/IlmBaseConfig.h" ilmbase_version_str - REGEX "^#define[\t ]+ILMBASE_VERSION_STRING[\t ]+\".*") + file(STRINGS "${IlmBase_INCLUDE_DIR}/ImathConfig.h" ilmbase_version_str + REGEX "^#define[\t ]+IMATH_VERSION_STRING[\t ]+\".*") - string(REGEX REPLACE "^#define[\t ]+ILMBASE_VERSION_STRING[\t ]+\"([^ \\n]*)\".*" - "\\1" IlmBase_VERSION "${ilmbase_version_str}") + string(REGEX REPLACE "^#define[\t ]+IMATH_VERSION_STRING[\t ]+\"([^ \\n]*)\".*" + "\\1" IlmBase_VERSION "${ilmbase_version_str}") unset(ilmbase_version_str) endif() endif() if("${IlmBase_VERSION}" VERSION_LESS "2.0.0") - set(IlmBase_ALL_LIBRARIES Imath Half Iex IlmThread) + set(IlmBase_ALL_LIBRARIES Imath-3_2 Iex-3_1 IlmThread-3_1) else() - set(IlmBase_ALL_LIBRARIES Imath Half Iex IexMath IlmThread) + set(IlmBase_ALL_LIBRARIES Imath-3_2 Iex-3_1 IlmThread-3_1) endif() foreach(ILMBASE_LIB ${IlmBase_ALL_LIBRARIES}) string(TOUPPER ${ILMBASE_LIB} _upper_ilmbase_lib) find_library(IlmBase_${_upper_ilmbase_lib}_LIBRARY - NAMES ${ILMBASE_LIB} lib${ILMBASE_LIB} - HINTS ${_IlmBase_HINT_LIB} + NAMES ${ILMBASE_LIB} lib${ILMBASE_LIB} + HINTS ${_IlmBase_HINT_LIB} ) if(IlmBase_${_upper_ilmbase_lib}_LIBRARY) set(IlmBase_LIBRARY ${IlmBase_LIBRARY} ${IlmBase_${_upper_ilmbase_lib}_LIBRARY}) @@ -69,20 +71,26 @@ endforeach() unset(_IlmBase_HINT_INCLUDE) unset(_IlmBase_HINT_LIB) set(IlmBase_LIBRARIES ${IlmBase_LIBRARY} ) -set(IlmBase_INCLUDE_DIRS ${IlmBase_INCLUDE_DIR} ) +set(IlmBase_INCLUDE_DIRS ${IlmBase_INCLUDE_DIR} + ${CMAKE_PREFIX_PATH}/include/OpenEXR ) if(NOT PC_ILMBASE_FOUND) -get_filename_component(IlmBase_LDFLAGS_OTHER ${IlmBase_HALF_LIBRARY} PATH) -set(IlmBase_LDFLAGS_OTHER -L${IlmBase_LDFLAGS_OTHER}) + get_filename_component(IlmBase_LDFLAGS_OTHER ${IlmBase_IMATH-3_1_LIBRARY} PATH) +if(WIN32) + set(IlmBase_LDFLAGS_OTHER -LIBPATH:${IlmBase_LDFLAGS_OTHER}) +else(WIN32) + set(IlmBase_LDFLAGS_OTHER -L${IlmBase_LDFLAGS_OTHER}) +endif(WIN32) endif() include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set IlmBase_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(IlmBase - REQUIRED_VARS IlmBase_LIBRARY IlmBase_INCLUDE_DIR - VERSION_VAR IlmBase_VERSION - FAIL_MESSAGE "Unable to find IlmBase libraries" ) + REQUIRED_VARS IlmBase_LIBRARY IlmBase_INCLUDE_DIR + VERSION_VAR IlmBase_VERSION + FAIL_MESSAGE "Unable to find IlmBase libraries" ) + # older versions of cmake don't support FOUND_VAR to find_package_handle # so just do it the hard way... diff --git a/cmake/modules/FindOpenEXR.cmake b/cmake/modules/FindOpenEXR.cmake index 40c1baa3..fefeb9ba 100644 --- a/cmake/modules/FindOpenEXR.cmake +++ b/cmake/modules/FindOpenEXR.cmake @@ -23,8 +23,8 @@ if(PC_OPENEXR_FOUND) set(OpenEXR_LIBRARY_DIRS ${PC_OPENEXR_LIBRARY_DIRS}) set(OpenEXR_LDFLAGS ${PC_OPENEXR_LDFLAGS_OTHER}) if("${_OpenEXR_HINT_INCLUDE}" STREQUAL "") - set(_OpenEXR_HINT_INCLUDE ${PC_OPENEXR_INCLUDEDIR} ${PC_OPENEXR_INCLUDE_DIRS}) - set(_OpenEXR_HINT_LIB ${PC_OPENEXR_LIBDIR} ${PC_OPENEXR_LIBRARY_DIRS}) + set(_OpenEXR_HINT_INCLUDE ${CMAKE_PREFIX_PATH}/include ) + set(_OpenEXR_HINT_LIB ${CMAKE_PREFIX_PATH}/lib ${CMAKE_PREFIX_PATH}/lib64 ) endif() else() if(UNIX) @@ -37,43 +37,48 @@ else() endif() find_path(OpenEXR_INCLUDE_DIR OpenEXRConfig.h - HINTS ${_OpenEXR_HINT_INCLUDE} - PATH_SUFFIXES OpenEXR ) + HINTS ${_OpenEXR_HINT_INCLUDE} + PATH_SUFFIXES OpenEXR ) if(OpenEXR_INCLUDE_DIR AND EXISTS "${OpenEXR_INCLUDE_DIR}/OpenEXRConfig.h") - set(OpenEXR_VERSION ${PC_OPENEXR_VERSION}) + #set(OpenEXR_VERSION ${PC_OPENEXR_VERSION}) if("${OpenEXR_VERSION}" STREQUAL "") file(STRINGS "${OpenEXR_INCLUDE_DIR}/OpenEXRConfig.h" openexr_version_str - REGEX "^#define[\t ]+OPENEXR_VERSION_STRING[\t ]+\".*") + REGEX "^#define[\t ]+OPENEXR_VERSION_STRING[\t ]+\".*") string(REGEX REPLACE "^#define[\t ]+OPENEXR_VERSION_STRING[\t ]+\"([^ \\n]*)\".*" - "\\1" OpenEXR_VERSION "${openexr_version_str}") + "\\1" OpenEXR_VERSION "${openexr_version_str}") unset(openexr_version_str) endif() endif() -find_library(OpenEXR_LIBRARY NAMES IlmImf libIlmImf HINTS ${_OpenEXR_HINT_LIB}) - +find_library(OpenEXR_LIBRARY NAMES OpenEXR-3_1 HINTS ${_OpenEXR_HINT_LIB}) +find_library(OpenEXRCore_LIBRARY NAMES OpenEXRCore-3_1 HINTS ${_OpenEXR_HINT_LIB}) +find_library(IlmImfUtil NAMES OpenEXRUtil-3_1 HINTS ${_OpenEXR_HINT_LIB}) find_package(IlmBase QUIET) unset(_OpenEXR_HINT_INCLUDE) unset(_OpenEXR_HINT_LIB) -set(OpenEXR_LIBRARIES ${OpenEXR_LIBRARY} ${IlmBase_LIBRARIES} ) +set(OpenEXR_LIBRARIES ${OpenEXR_LIBRARY} ${IlmImfUtil} ${OpenEXRCore_LIBRARY} ${IlmBase_LIBRARIES} ) set(OpenEXR_INCLUDE_DIRS ${OpenEXR_INCLUDE_DIR} ) if(NOT PC_OPENEXR_FOUND) get_filename_component(OpenEXR_LDFLAGS_OTHER ${OpenEXR_LIBRARY} PATH) +if(WIN32) +set(OpenEXR_LDFLAGS_OTHER -LIBPATH:${OpenEXR_LDFLAGS_OTHER}) +else(WIN32) set(OpenEXR_LDFLAGS_OTHER -L${OpenEXR_LDFLAGS_OTHER}) +endif(WIN32) endif() include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set OpenEXR_FOUND to TRUE # if all listed variables are TRUE find_package_handle_standard_args(OpenEXR - REQUIRED_VARS OpenEXR_LIBRARY OpenEXR_INCLUDE_DIR - VERSION_VAR OpenEXR_VERSION - FAIL_MESSAGE "Unable to find OpenEXR library" ) + REQUIRED_VARS OpenEXR_LIBRARY OpenEXR_INCLUDE_DIR + VERSION_VAR OpenEXR_VERSION + FAIL_MESSAGE "Unable to find OpenEXR library" ) # older versions of cmake don't support FOUND_VAR to find_package_handle # so just do it the hard way... diff --git a/ctlrender/CMakeLists.txt b/ctlrender/CMakeLists.txt index 9fced147..65f4c53e 100644 --- a/ctlrender/CMakeLists.txt +++ b/ctlrender/CMakeLists.txt @@ -1,4 +1,5 @@ + if (TIFF_FOUND) add_definitions( -DHAVE_LIBTIFF=1 ) include_directories( ${TIFF_INCLUDE_DIRS} ) @@ -6,6 +7,9 @@ link_directories( ${TIFF_LIBRARY_DIRS} ) endif() if ( OpenEXR_FOUND ) +if(WIN32) + add_definitions( -DOPENEXR_DLL -DNOMINMAX ) +endif(WIN32) add_definitions( -DHAVE_OPENEXR=1 ) include_directories( ${OpenEXR_INCLUDE_DIRS} ) link_directories( ${OpenEXR_LIBRARY_DIRS} ) @@ -17,6 +21,9 @@ include_directories( ${AcesContainer_INCLUDE_DIRS} ) link_directories( ${AcesContainer_LIBRARY_DIRS} ) endif() +add_definitions( -DDPX_DLL ) + + include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/lib/IlmCtl" "${PROJECT_SOURCE_DIR}/lib/IlmCtlMath" "${PROJECT_SOURCE_DIR}/lib/IlmCtlSimd" "${PROJECT_SOURCE_DIR}/lib/dpx" ) add_executable( ctlrender @@ -31,7 +38,14 @@ add_executable( ctlrender compression.cc ) -target_link_libraries( ctlrender IlmCtlSimd IlmCtlMath IlmCtl ctldpx ${IlmBase_LIBRARIES} ) +if(WIN32) + set( OS_LIBRARIES Winmm ) +else(WIN32) + set( OS_LIBRARIES "" ) +endif(WIN32) + +target_link_libraries( ctlrender IlmCtlSimd IlmCtlMath IlmCtl ctldpx ${OS_LIBRARIES} ) +target_link_libraries( ctlrender ${IlmBase_LIBRARIES} ) target_link_libraries( ctlrender ${IlmBase_LDFLAGS_OTHER} ) if (TIFF_FOUND) target_link_libraries( ctlrender ${TIFF_LIBRARIES} ) diff --git a/ctlrender/exr_file.hh b/ctlrender/exr_file.hh index 100244c8..a00af4c9 100644 --- a/ctlrender/exr_file.hh +++ b/ctlrender/exr_file.hh @@ -1,54 +1,54 @@ /////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2013 Academy of Motion Picture Arts and Sciences +// Copyright (c) 2013 Academy of Motion Picture Arts and Sciences // ("A.M.P.A.S."). Portions contributed by others as indicated. // All rights reserved. -// +// // A worldwide, royalty-free, non-exclusive right to copy, modify, create -// derivatives, and use, in source and binary forms, is hereby granted, -// subject to acceptance of this license. Performance of any of the -// aforementioned acts indicates acceptance to be bound by the following +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following // terms and conditions: // -// * Copies of source code, in whole or in part, must retain the -// above copyright notice, this list of conditions and the +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the // Disclaimer of Warranty. // -// * Use in binary form must retain the above copyright notice, +// * Use in binary form must retain the above copyright notice, // this list of conditions and the Disclaimer of Warranty in the // documentation and/or other materials provided with the distribution. // -// * Nothing in this license shall be deemed to grant any rights to -// trademarks, copyrights, patents, trade secrets or any other -// intellectual property of A.M.P.A.S. or any contributors, except +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except // as expressly stated herein. // -// * Neither the name "A.M.P.A.S." nor the name of any other -// contributors to this software may be used to endorse or promote -// products derivative of or based on this software without express -// prior written permission of A.M.P.A.S. or the contributors, as +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as // appropriate. -// -// This license shall be construed pursuant to the laws of the State of -// California, and any disputes related thereto shall be subject to the +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the // jurisdiction of the courts therein. // -// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND -// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO -// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, -// 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 +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// 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. // -// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY -// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER -// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY -// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER // THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. /////////////////////////////////////////////////////////////////////////// @@ -57,6 +57,7 @@ #include "main.hh" #include +#include bool exr_read(const char *name, float scale, ctl::dpx::fb *pixels, diff --git a/ctlrender/main.cc b/ctlrender/main.cc index 152bc13e..dd04334b 100644 --- a/ctlrender/main.cc +++ b/ctlrender/main.cc @@ -56,7 +56,17 @@ #include #include #include +#ifdef WIN32 +#include +#define MAXPATHLEN 1024 +#define strtof strtod +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#define F_OK 0 /* Test for existence. */ +#define access _access +#else #include +#endif #include #include "transform.hh" #include diff --git a/ctlrender/main.hh b/ctlrender/main.hh index a0bc0bd0..7e4ae807 100644 --- a/ctlrender/main.hh +++ b/ctlrender/main.hh @@ -1,3 +1,4 @@ + /////////////////////////////////////////////////////////////////////////// // Copyright (c) 2013 Academy of Motion Picture Arts and Sciences // ("A.M.P.A.S."). Portions contributed by others as indicated. @@ -56,7 +57,11 @@ #define CTL_UTIL_CTLRENDER_MAIN_INCLUDE #include +#ifdef WIN32 +#include +#else #include +#endif #include #include diff --git a/ctlrender/tiff_file.cc b/ctlrender/tiff_file.cc index 5621016c..47df3b6e 100644 --- a/ctlrender/tiff_file.cc +++ b/ctlrender/tiff_file.cc @@ -58,10 +58,13 @@ #if defined(HAVE_LIBTIFF) #include #include +#ifdef WIN32 +#else #include +#include +#endif #include #include -#include void tiff_read_multiplane(TIFF *t, float scale, ctl::dpx::fb * pixels); void tiff_read_interleaved(TIFF *t, float scale, ctl::dpx::fb * pixels); diff --git a/ctlrender/transform.cc b/ctlrender/transform.cc index e8f1a960..779636e2 100644 --- a/ctlrender/transform.cc +++ b/ctlrender/transform.cc @@ -57,6 +57,11 @@ #include "tiff_file.hh" #include "exr_file.hh" #include "aces_file.hh" +#ifdef WIN32 +#include +#define strcasecmp stricmp +#define snprintf _snprintf +#endif #include #include #include @@ -74,19 +79,19 @@ typedef Ctl::RcPtr CTLResultPtr; // class which holds the data resulting from a CTL transform class CTLResult: public Ctl::RcObject { -public: - CTLResult(); - virtual ~CTLResult(); + public: + CTLResult(); + virtual ~CTLResult(); - Ctl::TypeStoragePtr data; - bool external; - std::string alt_name; + Ctl::TypeStoragePtr data; + bool external; + std::string alt_name; }; CTLResult::CTLResult() : - Ctl::RcObject() +Ctl::RcObject() { - external = FALSE; + external = FALSE; } CTLResult::~CTLResult() @@ -101,260 +106,260 @@ typedef std::list CTLResults; // by a CTL function takes precedence void add_parameter_value_to_ctl_results(CTLResults *ctl_results, const ctl_parameter_t &ctl_parameter) { - CTLResults::iterator results_iter; - Ctl::ArrayTypePtr array; - Ctl::DataTypePtr type; - CTLResultPtr ctl_result; - - // lookup a named data element that matches the parameter name. - for (results_iter = ctl_results->begin(); results_iter != ctl_results->end(); results_iter++) - { - if ((*results_iter)->data->name() == ctl_parameter.name) - { - break; - } - } - - if (results_iter != ctl_results->end()) - { - // result data found - ctl_result = *results_iter; - - // if result data was set by a CTL function (i.e. external == false), we preserve its value - if (!ctl_result->external) - { - // Set by a CTL function. No way are we over writing this... - return; - } - // It's a command line argument, so we (re)set it (this happens - // if the user has specified the same parameter more than once - // (either due to user error or by overriding a global value with - // a local one). - } - else - { - // ctl result data not found, so we create a new ctl result and add it to the list (the ctl data value is added below) - ctl_result = CTLResultPtr(new CTLResult); - ctl_result->external = TRUE; - ctl_results->push_back(ctl_result); - } - - if (ctl_parameter.count == 1) - { - ctl_result->data = new Ctl::DataArg(ctl_parameter.name, new Ctl::StdFloatType(), 1); - ctl_result->data->set(&(ctl_parameter.value[0])); - } - else - { - type = new Ctl::StdArrayType(new Ctl::StdFloatType(), ctl_parameter.count); - ctl_result->data = new Ctl::DataArg(ctl_parameter.name, type, 1); - for (uint8_t i = 0; i < ctl_parameter.count; i++) - { - ctl_result->data->set(&(ctl_parameter.value[i]), 0, 0, 1, "%d", i); - } - } - ctl_results->push_back(ctl_result); + CTLResults::iterator results_iter; + Ctl::ArrayTypePtr array; + Ctl::DataTypePtr type; + CTLResultPtr ctl_result; + + // lookup a named data element that matches the parameter name. + for (results_iter = ctl_results->begin(); results_iter != ctl_results->end(); results_iter++) + { + if ((*results_iter)->data->name() == ctl_parameter.name) + { + break; + } + } + + if (results_iter != ctl_results->end()) + { + // result data found + ctl_result = *results_iter; + + // if result data was set by a CTL function (i.e. external == false), we preserve its value + if (!ctl_result->external) + { + // Set by a CTL function. No way are we over writing this... + return; + } + // It's a command line argument, so we (re)set it (this happens + // if the user has specified the same parameter more than once + // (either due to user error or by overriding a global value with + // a local one). + } + else + { + // ctl result data not found, so we create a new ctl result and add it to the list (the ctl data value is added below) + ctl_result = CTLResultPtr(new CTLResult); + ctl_result->external = TRUE; + ctl_results->push_back(ctl_result); + } + + if (ctl_parameter.count == 1) + { + ctl_result->data = new Ctl::DataArg(ctl_parameter.name, new Ctl::StdFloatType(), 1); + ctl_result->data->set(&(ctl_parameter.value[0])); + } + else + { + type = new Ctl::StdArrayType(new Ctl::StdFloatType(), ctl_parameter.count); + ctl_result->data = new Ctl::DataArg(ctl_parameter.name, type, 1); + for (uint8_t i = 0; i < ctl_parameter.count; i++) + { + ctl_result->data->set(&(ctl_parameter.value[i]), 0, 0, 1, "%d", i); + } + } + ctl_results->push_back(ctl_result); } void set_ctl_function_argument_from_ctl_results(Ctl::FunctionArgPtr *arg, const CTLResults &ctl_results, size_t offset, size_t count) { - CTLResults::const_iterator results_iter; - Ctl::TypeStoragePtr src; - Ctl::FunctionArgPtr dst; - - dst = *arg; - - for (results_iter = ctl_results.begin(); results_iter != ctl_results.end(); results_iter++) - { - if ((*results_iter)->data->name() == dst->name() || (*results_iter)->alt_name == dst->name()) - { - break; - } - } - - if (results_iter == ctl_results.end()) - { - if (dst->hasDefaultValue()) - { - dst->setDefaultValue(); - } - else - { - THROW(Iex::ArgExc, "CTL parameter '" << dst->name() << "' not specified on the command line and does not have a default value."); - throw(std::exception()); - } - return; - } - - src = (*results_iter)->data; - if (!dst->isVarying()) - { - if (offset == 0) - { - dst->copy(src, 0, 0, 1); - } - return; - } - else - { - if (!src->isVarying()) - { - for (size_t i = 0; i < dst->elements(); i++) - { - dst->copy(src, 0, i, 1); - } - } - else - { - dst->copy(src, offset, 0, count); - } - } + CTLResults::const_iterator results_iter; + Ctl::TypeStoragePtr src; + Ctl::FunctionArgPtr dst; + + dst = *arg; + + for (results_iter = ctl_results.begin(); results_iter != ctl_results.end(); results_iter++) + { + if ((*results_iter)->data->name() == dst->name() || (*results_iter)->alt_name == dst->name()) + { + break; + } + } + + if (results_iter == ctl_results.end()) + { + if (dst->hasDefaultValue()) + { + dst->setDefaultValue(); + } + else + { + THROW(Iex::ArgExc, "CTL parameter '" << dst->name() << "' not specified on the command line and does not have a default value."); + throw(std::exception()); + } + return; + } + + src = (*results_iter)->data; + if (!dst->isVarying()) + { + if (offset == 0) + { + dst->copy(src, 0, 0, 1); + } + return; + } + else + { + if (!src->isVarying()) + { + for (size_t i = 0; i < dst->elements(); i++) + { + dst->copy(src, 0, i, 1); + } + } + else + { + dst->copy(src, offset, 0, count); + } + } } void set_ctl_results_from_ctl_function_argument(CTLResults *ctl_results, const Ctl::FunctionArgPtr &arg, size_t offset, size_t count, size_t total) { - CTLResults::iterator results_iter; - CTLResultPtr ctl_result; + CTLResults::iterator results_iter; + CTLResultPtr ctl_result; - for (results_iter = ctl_results->begin(); results_iter != ctl_results->end(); results_iter++) - { - if ((*results_iter)->data->name() == arg->name()) - { - break; - } - } + for (results_iter = ctl_results->begin(); results_iter != ctl_results->end(); results_iter++) + { + if ((*results_iter)->data->name() == arg->name()) + { + break; + } + } // fprintf(stderr, "copying %d@%d (total %d) of %s\n", count, offset, total, arg->name().c_str()); - if (!arg->isVarying()) - { - // For constant return arguments we only do this the first time - // through - if (offset != 0) - { - return; - } - total = 1; - count = 1; - } - - // Since the ctl_results list gets rebuilt after the end of ctl_run_transform - // we don't have to worry about having this function getting called - // twice with the FunctionArgPtr having different types (for a given - // output argument name). - if (results_iter != ctl_results->end()) - { - ctl_result = *results_iter; - - std::string inputName; - if (arg->name() == "rOut") - { - inputName = "rIn"; - } - else if (arg->name() == "gOut") - { - inputName = "gIn"; - } - else if (arg->name() == "bOut") - { - inputName = "bIn"; - } - else if (arg->name() == "aOut") - { - inputName = "aIn"; - } - - if (!inputName.empty()) - { - for (results_iter = ctl_results->begin(); results_iter != ctl_results->end(); results_iter++) - { - if ((*results_iter)->data->name() == inputName) - { - break; - } - } - - if (results_iter != ctl_results->end()) - { - CTLResultPtr ctl_result_output_to_input; - ctl_result_output_to_input = *results_iter; - ctl_result_output_to_input->data->copy(arg, 0, offset, count); - } - - } - } - else - { - ctl_result = CTLResultPtr(new CTLResult()); - ctl_result->data = new Ctl::DataArg(arg->name(), arg->type(), total); - ctl_results->push_back(ctl_result); - - std::string inputName; - if (arg->name() == "rOut") - { - inputName = "rIn"; - } - else if (arg->name() == "gOut") - { - inputName = "gIn"; - } - else if (arg->name() == "bOut") - { - inputName = "bIn"; - } - else if (arg->name() == "aOut") - { - inputName = "aIn"; - } - - if (!inputName.empty()) - { - CTLResultPtr ctl_result_input; - - ctl_result_input = CTLResultPtr(new CTLResult()); - ctl_result_input->data = new Ctl::DataArg(inputName, arg->type(), total); - ctl_results->push_back(ctl_result_input); - ctl_result_input->data->copy(arg, 0, offset, count); - } - } - - ctl_result->data->copy(arg, 0, offset, count); + if (!arg->isVarying()) + { + // For constant return arguments we only do this the first time + // through + if (offset != 0) + { + return; + } + total = 1; + count = 1; + } + + // Since the ctl_results list gets rebuilt after the end of ctl_run_transform + // we don't have to worry about having this function getting called + // twice with the FunctionArgPtr having different types (for a given + // output argument name). + if (results_iter != ctl_results->end()) + { + ctl_result = *results_iter; + + std::string inputName; + if (arg->name() == "rOut") + { + inputName = "rIn"; + } + else if (arg->name() == "gOut") + { + inputName = "gIn"; + } + else if (arg->name() == "bOut") + { + inputName = "bIn"; + } + else if (arg->name() == "aOut") + { + inputName = "aIn"; + } + + if (!inputName.empty()) + { + for (results_iter = ctl_results->begin(); results_iter != ctl_results->end(); results_iter++) + { + if ((*results_iter)->data->name() == inputName) + { + break; + } + } + + if (results_iter != ctl_results->end()) + { + CTLResultPtr ctl_result_output_to_input; + ctl_result_output_to_input = *results_iter; + ctl_result_output_to_input->data->copy(arg, 0, offset, count); + } + + } + } + else + { + ctl_result = CTLResultPtr(new CTLResult()); + ctl_result->data = new Ctl::DataArg(arg->name(), arg->type(), total); + ctl_results->push_back(ctl_result); + + std::string inputName; + if (arg->name() == "rOut") + { + inputName = "rIn"; + } + else if (arg->name() == "gOut") + { + inputName = "gIn"; + } + else if (arg->name() == "bOut") + { + inputName = "bIn"; + } + else if (arg->name() == "aOut") + { + inputName = "aIn"; + } + + if (!inputName.empty()) + { + CTLResultPtr ctl_result_input; + + ctl_result_input = CTLResultPtr(new CTLResult()); + ctl_result_input->data = new Ctl::DataArg(inputName, arg->type(), total); + ctl_results->push_back(ctl_result_input); + ctl_result_input->data->copy(arg, 0, offset, count); + } + } + + ctl_result->data->copy(arg, 0, offset, count); } void run_ctl_transform(const ctl_operation_t &ctl_operation, CTLResults *ctl_results, size_t count) { - Ctl::SimdInterpreter interpreter; - Ctl::FunctionCallPtr fn; - Ctl::FunctionArgPtr arg; - CTLResults::iterator results_iter; - char *name = NULL; - char *module; - char *slash; - char *dot; - CTLResults new_ctl_results; - - try - { - - name = (char *) alloca(strlen(ctl_operation.filename)+1); - memset(name, 0, strlen(ctl_operation.filename) + 1); - strcpy(name, ctl_operation.filename); - - // XXX probably not windows friendly - slash = strrchr(name, '/'); - if (slash == NULL) - { - module = name; - } - else - { - module = slash + 1; - } - - dot = strrchr(module, '.'); - if (dot != NULL) - { - *dot = 0; - } + Ctl::SimdInterpreter interpreter; + Ctl::FunctionCallPtr fn; + Ctl::FunctionArgPtr arg; + CTLResults::iterator results_iter; + char *name = NULL; + char *module; + char *slash; + char *dot; + CTLResults new_ctl_results; + + try + { + + name = (char *) alloca(strlen(ctl_operation.filename)+1); + memset(name, 0, strlen(ctl_operation.filename) + 1); + strcpy(name, ctl_operation.filename); + + // XXX probably not windows friendly + slash = strrchr(name, '/'); + if (slash == NULL) + { + module = name; + } + else + { + module = slash + 1; + } + + dot = strrchr(module, '.'); + if (dot != NULL) + { + *dot = 0; + } interpreter.loadFile(ctl_operation.filename); @@ -384,99 +389,99 @@ void run_ctl_transform(const ctl_operation_t &ctl_operation, CTLResults *ctl_res } - if (fn->returnValue()->type().cast().refcount() == 0) - { - THROW(Iex::ArgExc, "CTL main (or ) function must return a 'void'"); - } - - if (verbosity > 1) - { - fprintf(stderr, " ctl script file: %s\n", ctl_operation.filename); - fprintf(stderr, " function name: %s\n", fn->name().c_str()); - - for (size_t i = 0; i < fn->numInputArgs(); i++) - { - arg = fn->inputArg(i); - if (i == 0) - { - fprintf(stderr, " input arguments:\n"); - } - fprintf(stderr, "%18s: %s", arg->name().c_str(), arg->type()->asString().c_str()); - - if (arg->isVarying()) - { - fprintf(stderr, " (varying)"); - } - - if (arg->hasDefaultValue()) - { - fprintf(stderr, " (defaulted)"); - } - - fprintf(stderr, "\n"); - } - - for (size_t i = 0; i < fn->numOutputArgs(); i++) - { - arg = fn->outputArg(i); - if (i == 0) - { - fprintf(stderr, " output arguments:\n"); - } - - fprintf(stderr, "%18s: %s", arg->name().c_str(), arg->type()->asString().c_str()); - - if (arg->isVarying()) - { - fprintf(stderr, " (varying)"); - } - - if (arg->hasDefaultValue()) - { - fprintf(stderr, " (defaulted)"); - } - - fprintf(stderr, "\n"); - } - fprintf(stderr, "\n"); - } - - // fprintf(stderr, "%d samples to go.\n", count); - - size_t offset = 0; - while (offset < count) - { - size_t pass = interpreter.maxSamples(); - if (pass > (count - offset)) - { - pass = (count - offset); - } + if (fn->returnValue()->type().cast().refcount() == 0) + { + THROW(Iex::ArgExc, "CTL main (or ) function must return a 'void'"); + } + + if (verbosity > 1) + { + fprintf(stderr, " ctl script file: %s\n", ctl_operation.filename); + fprintf(stderr, " function name: %s\n", fn->name().c_str()); + + for (size_t i = 0; i < fn->numInputArgs(); i++) + { + arg = fn->inputArg(i); + if (i == 0) + { + fprintf(stderr, " input arguments:\n"); + } + fprintf(stderr, "%18s: %s", arg->name().c_str(), arg->type()->asString().c_str()); + + if (arg->isVarying()) + { + fprintf(stderr, " (varying)"); + } + + if (arg->hasDefaultValue()) + { + fprintf(stderr, " (defaulted)"); + } + + fprintf(stderr, "\n"); + } + + for (size_t i = 0; i < fn->numOutputArgs(); i++) + { + arg = fn->outputArg(i); + if (i == 0) + { + fprintf(stderr, " output arguments:\n"); + } + + fprintf(stderr, "%18s: %s", arg->name().c_str(), arg->type()->asString().c_str()); + + if (arg->isVarying()) + { + fprintf(stderr, " (varying)"); + } + + if (arg->hasDefaultValue()) + { + fprintf(stderr, " (defaulted)"); + } + + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + } + + // fprintf(stderr, "%d samples to go.\n", count); + + size_t offset = 0; + while (offset < count) + { + size_t pass = interpreter.maxSamples(); + if (pass > (count - offset)) + { + pass = (count - offset); + } // fprintf(stderr, "at offset %d doing %d samples\n", offset, pass); - for (size_t i = 0; i < fn->numInputArgs(); i++) - { - arg = fn->inputArg(i); - set_ctl_function_argument_from_ctl_results(&arg, *ctl_results, offset, pass); - } - - fn->callFunction(pass); - - for (size_t i = 0; i < fn->numOutputArgs(); i++) - { - //printf("setting results from function argument\n"); - set_ctl_results_from_ctl_function_argument(&new_ctl_results, fn->outputArg(i), offset, pass, count); - } - - offset = offset + pass; - } - *ctl_results = new_ctl_results; - } - catch (...) - { + for (size_t i = 0; i < fn->numInputArgs(); i++) + { + arg = fn->inputArg(i); + set_ctl_function_argument_from_ctl_results(&arg, *ctl_results, offset, pass); + } + + fn->callFunction(pass); + + for (size_t i = 0; i < fn->numOutputArgs(); i++) + { + //printf("setting results from function argument\n"); + set_ctl_results_from_ctl_function_argument(&new_ctl_results, fn->outputArg(i), offset, pass, count); + } + + offset = offset + pass; + } + *ctl_results = new_ctl_results; + } + catch (...) + { // if(name!=NULL) { // free(name); // } - throw; - } + throw; + } } @@ -484,106 +489,106 @@ void run_ctl_transform(const ctl_operation_t &ctl_operation, CTLResults *ctl_res // Copies a new CTL result (block of data) from the framebuffer fb. CTLResultPtr mkresult(const char *name, const char *alt_name, const ctl::dpx::fb &fb, size_t offset) { - CTLResultPtr new_result = CTLResultPtr(new CTLResult()); + CTLResultPtr new_result = CTLResultPtr(new CTLResult()); - // DataArg represents a raw block of data - // XXX - seems like last argument to Ctl::DataArg should be (fb.pixels() + offset) because the argument represents the data size (i.e. number of bytes) - new_result->data = Ctl::DataArgPtr(new Ctl::DataArg(name, Ctl::DataTypePtr(new Ctl::StdFloatType()), fb.pixels())); + // DataArg represents a raw block of data + // XXX - seems like last argument to Ctl::DataArg should be (fb.pixels() + offset) because the argument represents the data size (i.e. number of bytes) + new_result->data = Ctl::DataArgPtr(new Ctl::DataArg(name, Ctl::DataTypePtr(new Ctl::StdFloatType()), fb.pixels())); - if (alt_name != NULL) - { - new_result->alt_name = alt_name; - } + if (alt_name != NULL) + { + new_result->alt_name = alt_name; + } - new_result->data->set(fb.ptr() + offset, sizeof(float) * fb.depth(), 0, fb.pixels()); + new_result->data->set(fb.ptr() + offset, sizeof(float) * fb.depth(), 0, fb.pixels()); - return new_result; + return new_result; } void mkimage(ctl::dpx::fb *image_buffer, const CTLResults &ctl_results, format_t *image_format) { - enum have_channel_e - { - // These need to be in the order that you want them in the file... - have_x = 0, - have_y = 1, - have_z = 2, - have_r = 3, - have_g = 4, - have_b = 5, - have_a = 6, - have_xout = 8, - have_yout = 9, - have_zout = 10, - have_rout = 11, - have_gout = 12, - have_bout = 13, - have_aout = 14, - mask_x = 1 << have_x, - mask_y = 1 << have_y, - mask_z = 1 << have_z, - mask_r = 1 << have_r, - mask_g = 1 << have_g, - mask_b = 1 << have_b, - mask_a = 1 << have_a, - mask_xout = 1 << have_xout, - mask_yout = 1 << have_yout, - mask_zout = 1 << have_zout, - mask_rout = 1 << have_rout, - mask_gout = 1 << have_gout, - mask_bout = 1 << have_bout, - mask_aout = 1 << have_aout, - have_none = 33, - }; - - CTLResults::const_iterator results_iter; - CTLResultPtr channels[16]; - int channels_mask; - have_channel_e channel; - const char *channel_name; - uint8_t on_channel; - uint8_t channel_count; - uint8_t c; - CTLResultPtr ctl_result; - - // These need to be in the order for preferred output formats... - // The DPX colorimetric is in the top 8 bits - int tests[] = - { - (51 << 24) | (mask_rout | mask_gout | mask_bout | mask_aout), (50 << 24) - | (mask_rout | mask_gout | mask_bout), (158 << 24) - | (mask_xout | mask_yout | mask_zout | mask_aout), (157 << 24) - | (mask_xout | mask_yout | mask_zout), (159 << 24) - | (mask_yout | mask_aout), (6 << 24) | (mask_yout), (162 << 24) - | (mask_gout | mask_aout), (2 << 24) | (mask_gout), (161 << 24) - | (mask_bout | mask_aout), (3 << 24) | (mask_bout), (160 << 24) - | (mask_rout | mask_aout), (1 << 24) | (mask_rout), (4 << 24) - | (mask_aout), - - (51 << 24) | (mask_r | mask_g | mask_b | mask_a), (50 << 24) - | (mask_r | mask_g | mask_b), (158 << 24) - | (mask_x | mask_y | mask_z | mask_a), (159 << 24) - | (mask_y | mask_a), (6 << 24) | (mask_y), (162 << 24) - | (mask_g | mask_a), (2 << 24) | (mask_g), (161 << 24) - | (mask_b | mask_a), (3 << 24) | (mask_b), (160 << 24) - | (mask_r | mask_a), (1 << 24) | (mask_r), (4 << 24) | (mask_a), - - 0 - }; - - channels_mask = 0; - for (results_iter = ctl_results.begin(); results_iter != ctl_results.end(); results_iter++) - { - ctl_result = *results_iter; - if (!ctl_result->data->isVarying() && ctl_result->data->elements() != image_buffer->pixels()) - { - continue; - } - channel = have_none; - channel_name = ctl_result->data->name().c_str(); - if (0) - { - } + enum have_channel_e + { + // These need to be in the order that you want them in the file... + have_x = 0, + have_y = 1, + have_z = 2, + have_r = 3, + have_g = 4, + have_b = 5, + have_a = 6, + have_xout = 8, + have_yout = 9, + have_zout = 10, + have_rout = 11, + have_gout = 12, + have_bout = 13, + have_aout = 14, + mask_x = 1 << have_x, + mask_y = 1 << have_y, + mask_z = 1 << have_z, + mask_r = 1 << have_r, + mask_g = 1 << have_g, + mask_b = 1 << have_b, + mask_a = 1 << have_a, + mask_xout = 1 << have_xout, + mask_yout = 1 << have_yout, + mask_zout = 1 << have_zout, + mask_rout = 1 << have_rout, + mask_gout = 1 << have_gout, + mask_bout = 1 << have_bout, + mask_aout = 1 << have_aout, + have_none = 33, + }; + + CTLResults::const_iterator results_iter; + CTLResultPtr channels[16]; + int channels_mask; + have_channel_e channel; + const char *channel_name; + uint8_t on_channel; + uint8_t channel_count; + uint8_t c; + CTLResultPtr ctl_result; + + // These need to be in the order for preferred output formats... + // The DPX colorimetric is in the top 8 bits + int tests[] = + { + (51 << 24) | (mask_rout | mask_gout | mask_bout | mask_aout), (50 << 24) + | (mask_rout | mask_gout | mask_bout), (158 << 24) + | (mask_xout | mask_yout | mask_zout | mask_aout), (157 << 24) + | (mask_xout | mask_yout | mask_zout), (159 << 24) + | (mask_yout | mask_aout), (6 << 24) | (mask_yout), (162 << 24) + | (mask_gout | mask_aout), (2 << 24) | (mask_gout), (161 << 24) + | (mask_bout | mask_aout), (3 << 24) | (mask_bout), (160 << 24) + | (mask_rout | mask_aout), (1 << 24) | (mask_rout), (4 << 24) + | (mask_aout), + + (51 << 24) | (mask_r | mask_g | mask_b | mask_a), (50 << 24) + | (mask_r | mask_g | mask_b), (158 << 24) + | (mask_x | mask_y | mask_z | mask_a), (159 << 24) + | (mask_y | mask_a), (6 << 24) | (mask_y), (162 << 24) + | (mask_g | mask_a), (2 << 24) | (mask_g), (161 << 24) + | (mask_b | mask_a), (3 << 24) | (mask_b), (160 << 24) + | (mask_r | mask_a), (1 << 24) | (mask_r), (4 << 24) | (mask_a), + + 0 + }; + + channels_mask = 0; + for (results_iter = ctl_results.begin(); results_iter != ctl_results.end(); results_iter++) + { + ctl_result = *results_iter; + if (!ctl_result->data->isVarying() && ctl_result->data->elements() != image_buffer->pixels()) + { + continue; + } + channel = have_none; + channel_name = ctl_result->data->name().c_str(); + if (0) + { + } // else if(!strcasecmp("X", channel_name)) { channel=have_x; } // else if(!strcasecmp("Y", channel_name)) { channel=have_y; } // else if(!strcasecmp("Z", channel_name)) { channel=have_z; } @@ -594,79 +599,79 @@ void mkimage(ctl::dpx::fb *image_buffer, const CTLResults &ctl_results, f // else if(!strcasecmp("outX", channel_name)) { channel=have_xout; } // else if(!strcasecmp("outY", channel_name)) { channel=have_yout; } // else if(!strcasecmp("outZ", channel_name)) { channel=have_zout; } - else if (!strcasecmp("aOut", channel_name)) - { - channel = have_aout; - } - else if (!strcasecmp("rOut", channel_name)) - { - channel = have_rout; - } - else if (!strcasecmp("gOut", channel_name)) - { - channel = have_gout; - } - else if (!strcasecmp("bOut", channel_name)) - { - channel = have_bout; - } - - if (channel == have_none) - { - continue; - } - - if (ctl_result->data->type().cast().refcount() == 0 - && ctl_result->data->type().cast().refcount() == 0) - { - THROW(Iex::ArgExc, "CTL script not providing half or float as the output data type."); - } - channels[channel] = ctl_result; - channels_mask = channels_mask | (1 << channel); - } - - for (c = 0; tests[c] != 0; c++) - { - if ((channels_mask & tests[c] & 0x00ffffff) == (tests[c] & 0x00ffffff)) - { - channels_mask = tests[c]; - break; - } - } - - if (tests[c] == 0) - { - THROW(Iex::ArgExc, "Unable to determine what channels from the CTL script output should be saved."); - } - - channel_count = 0; - for (c = 0; c < 24; c++) - { - if (channels_mask & (1 << c)) - { - channel_count++; - } - } - - if (image_buffer->depth() != channel_count) - { - image_buffer->init(image_buffer->width(), image_buffer->height(), channel_count); - } - - on_channel = 0; - for (c = 0; c < 24; c++) - { - if (channels_mask & (1 << c)) - { - channels[c]->data->get(image_buffer->ptr() + on_channel, sizeof(float) * channel_count, 0, image_buffer->pixels()); - on_channel++; - } - } - - if (image_format->descriptor == 0) - { - image_format->descriptor = (channels_mask & 0xff000000) >> 24; - } + else if (!strcasecmp("aOut", channel_name)) + { + channel = have_aout; + } + else if (!strcasecmp("rOut", channel_name)) + { + channel = have_rout; + } + else if (!strcasecmp("gOut", channel_name)) + { + channel = have_gout; + } + else if (!strcasecmp("bOut", channel_name)) + { + channel = have_bout; + } + + if (channel == have_none) + { + continue; + } + + if (ctl_result->data->type().cast().refcount() == 0 + && ctl_result->data->type().cast().refcount() == 0) + { + THROW(Iex::ArgExc, "CTL script not providing half or float as the output data type."); + } + channels[channel] = ctl_result; + channels_mask = channels_mask | (1 << channel); + } + + for (c = 0; tests[c] != 0; c++) + { + if ((channels_mask & tests[c] & 0x00ffffff) == (tests[c] & 0x00ffffff)) + { + channels_mask = tests[c]; + break; + } + } + + if (tests[c] == 0) + { + THROW(Iex::ArgExc, "Unable to determine what channels from the CTL script output should be saved."); + } + + channel_count = 0; + for (c = 0; c < 24; c++) + { + if (channels_mask & (1 << c)) + { + channel_count++; + } + } + + if (image_buffer->depth() != channel_count) + { + image_buffer->init(image_buffer->width(), image_buffer->height(), channel_count); + } + + on_channel = 0; + for (c = 0; c < 24; c++) + { + if (channels_mask & (1 << c)) + { + channels[c]->data->get(image_buffer->ptr() + on_channel, sizeof(float) * channel_count, 0, image_buffer->pixels()); + on_channel++; + } + } + + if (image_format->descriptor == 0) + { + image_format->descriptor = (channels_mask & 0xff000000) >> 24; + } } // Currently we have no thread support. This would be nice but we will @@ -675,184 +680,184 @@ void mkimage(ctl::dpx::fb *image_buffer, const CTLResults &ctl_results, f // reader / writer and those will probably want to migrate back to the // calling function. void transform(const char *inputFile, const char *outputFile, - float input_scale, float output_scale, - format_t *image_format, + float input_scale, float output_scale, + format_t *image_format, Compression *compression, - const CTLOperations &ctl_operations, - const CTLParameters &global_parameters) + const CTLOperations &ctl_operations, + const CTLParameters &global_parameters) { - CTLOperations::const_iterator operations_iter; - ctl_operation_t ctl_operation; - CTLParameters::const_iterator parameters_iter; - uint8_t i; - std::string error; - ctl::dpx::fb image_buffer; - - if (verbosity > 1) - { - fprintf(stdout, " source file: %s\n", inputFile); - fprintf(stdout, " destination file: %s\n", outputFile); - fprintf(stderr, "destination format: %s\n", image_format->ext); - fprintf(stderr, " input scale: "); - if (input_scale == 0.0) - { - fprintf(stderr, "default\n"); - } - else - { - fprintf(stderr, "%f\n", input_scale); - } - fprintf(stderr, " output scale: "); - if (output_scale == 0.0) - { - fprintf(stderr, "default\n"); - } - else - { - fprintf(stderr, "%f\n", output_scale); - } - if (verbosity > 2) - { - i = 0; - for (parameters_iter = global_parameters.begin(); parameters_iter != global_parameters.end(); parameters_iter++) - { - if (i == 0) - { - fprintf(stderr, " global parameters:\n"); - i++; - } - fprintf(stderr, "%18s:", parameters_iter->name); - for (i = 0; i < parameters_iter->count; i++) - { - fprintf(stderr, " %f", parameters_iter->value[i]); - } - fprintf(stderr, "\n"); - } - for (operations_iter = ctl_operations.begin(); operations_iter != ctl_operations.end(); operations_iter++) - { - ctl_operation = *operations_iter; - fprintf(stderr, " ctl script file: %s\n", ctl_operation.filename); - if (verbosity > 3) - { - i = 0; - for (parameters_iter = ctl_operation.local.begin(); parameters_iter != ctl_operation.local.end(); parameters_iter++) - { - if (i == 0) - { - fprintf(stderr, " local parameters:\n"); - i++; - } - fprintf(stderr, "%18s:", parameters_iter->name); - for (i = 0; i < parameters_iter->count; i++) - { - fprintf(stderr, " %f", parameters_iter->value[i]); - } - fprintf(stderr, "\n"); - } - } - } - } - fprintf(stderr, "\n"); - } - - if (!dpx_read(inputFile, input_scale, &image_buffer, image_format) && - !exr_read(inputFile, input_scale, &image_buffer, image_format) && - !tiff_read(inputFile, input_scale, &image_buffer, image_format)) - { - fprintf(stderr, "unable to read file %s (unknown format).\n", inputFile); - exit(1); - } - - if (output_scale != 0.0) - { - output_scale = output_scale / 1.0; - } - if (image_format->bps == 0) - { - image_format->bps = image_format->src_bps; - } - - CTLResults ctl_results; - - if (image_buffer.depth() > 0) - { - ctl_results.push_back(mkresult("rIn", "c00In", image_buffer, 0)); - } - if (image_buffer.depth() > 1) - { - ctl_results.push_back(mkresult("gIn", "c01In", image_buffer, 1)); - } - if (image_buffer.depth() > 2) - { - ctl_results.push_back(mkresult("bIn", "c02In", image_buffer, 2)); - } - if (image_buffer.depth() > 3) - { - ctl_results.push_back(mkresult("aIn", "c03In", image_buffer, 3)); - } - - char name[16]; - - for (i = 4; i < image_buffer.depth(); i++) - { - memset(name, 0, sizeof(name)); - snprintf(name, sizeof(name) - 1, "c%02dIn", i); - ctl_results.push_back(mkresult(name, NULL, image_buffer, i)); - } - - for (operations_iter = ctl_operations.begin(); operations_iter != ctl_operations.end(); operations_iter++) - { - ctl_operation = *operations_iter; - for (parameters_iter = global_parameters.begin(); parameters_iter != global_parameters.end(); parameters_iter++) - { - add_parameter_value_to_ctl_results(&ctl_results, *parameters_iter); - } - for (parameters_iter = ctl_operation.local.begin(); parameters_iter != ctl_operation.local.end(); parameters_iter++) - { - add_parameter_value_to_ctl_results(&ctl_results, *parameters_iter); - } - - // Output is used to pass output parameters from script to the next. - run_ctl_transform(*operations_iter, &ctl_results, image_buffer.pixels()); - } - - mkimage(&image_buffer, ctl_results, image_format); - - if (output_scale != 0.0) - { - output_scale = output_scale / 1.0; - } - if (image_format->squish) - { - image_buffer.swizzle(0, TRUE); - } + CTLOperations::const_iterator operations_iter; + ctl_operation_t ctl_operation; + CTLParameters::const_iterator parameters_iter; + uint8_t i; + std::string error; + ctl::dpx::fb image_buffer; + + if (verbosity > 1) + { + fprintf(stdout, " source file: %s\n", inputFile); + fprintf(stdout, " destination file: %s\n", outputFile); + fprintf(stderr, "destination format: %s\n", image_format->ext); + fprintf(stderr, " input scale: "); + if (input_scale == 0.0) + { + fprintf(stderr, "default\n"); + } + else + { + fprintf(stderr, "%f\n", input_scale); + } + fprintf(stderr, " output scale: "); + if (output_scale == 0.0) + { + fprintf(stderr, "default\n"); + } + else + { + fprintf(stderr, "%f\n", output_scale); + } + if (verbosity > 2) + { + i = 0; + for (parameters_iter = global_parameters.begin(); parameters_iter != global_parameters.end(); parameters_iter++) + { + if (i == 0) + { + fprintf(stderr, " global parameters:\n"); + i++; + } + fprintf(stderr, "%18s:", parameters_iter->name); + for (i = 0; i < parameters_iter->count; i++) + { + fprintf(stderr, " %f", parameters_iter->value[i]); + } + fprintf(stderr, "\n"); + } + for (operations_iter = ctl_operations.begin(); operations_iter != ctl_operations.end(); operations_iter++) + { + ctl_operation = *operations_iter; + fprintf(stderr, " ctl script file: %s\n", ctl_operation.filename); + if (verbosity > 3) + { + i = 0; + for (parameters_iter = ctl_operation.local.begin(); parameters_iter != ctl_operation.local.end(); parameters_iter++) + { + if (i == 0) + { + fprintf(stderr, " local parameters:\n"); + i++; + } + fprintf(stderr, "%18s:", parameters_iter->name); + for (i = 0; i < parameters_iter->count; i++) + { + fprintf(stderr, " %f", parameters_iter->value[i]); + } + fprintf(stderr, "\n"); + } + } + } + } + fprintf(stderr, "\n"); + } + + if (!dpx_read(inputFile, input_scale, &image_buffer, image_format) && + !exr_read(inputFile, input_scale, &image_buffer, image_format) && + !tiff_read(inputFile, input_scale, &image_buffer, image_format)) + { + fprintf(stderr, "unable to read file %s (unknown format).\n", inputFile); + exit(1); + } + + if (output_scale != 0.0) + { + output_scale = output_scale / 1.0; + } + if (image_format->bps == 0) + { + image_format->bps = image_format->src_bps; + } + + CTLResults ctl_results; + + if (image_buffer.depth() > 0) + { + ctl_results.push_back(mkresult("rIn", "c00In", image_buffer, 0)); + } + if (image_buffer.depth() > 1) + { + ctl_results.push_back(mkresult("gIn", "c01In", image_buffer, 1)); + } + if (image_buffer.depth() > 2) + { + ctl_results.push_back(mkresult("bIn", "c02In", image_buffer, 2)); + } + if (image_buffer.depth() > 3) + { + ctl_results.push_back(mkresult("aIn", "c03In", image_buffer, 3)); + } + + char name[16]; + + for (i = 4; i < image_buffer.depth(); i++) + { + memset(name, 0, sizeof(name)); + snprintf(name, sizeof(name) - 1, "c%02dIn", i); + ctl_results.push_back(mkresult(name, NULL, image_buffer, i)); + } + + for (operations_iter = ctl_operations.begin(); operations_iter != ctl_operations.end(); operations_iter++) + { + ctl_operation = *operations_iter; + for (parameters_iter = global_parameters.begin(); parameters_iter != global_parameters.end(); parameters_iter++) + { + add_parameter_value_to_ctl_results(&ctl_results, *parameters_iter); + } + for (parameters_iter = ctl_operation.local.begin(); parameters_iter != ctl_operation.local.end(); parameters_iter++) + { + add_parameter_value_to_ctl_results(&ctl_results, *parameters_iter); + } + + // Output is used to pass output parameters from script to the next. + run_ctl_transform(*operations_iter, &ctl_results, image_buffer.pixels()); + } + + mkimage(&image_buffer, ctl_results, image_format); + + if (output_scale != 0.0) + { + output_scale = output_scale / 1.0; + } + if (image_format->squish) + { + image_buffer.swizzle(0, TRUE); + } // std::cout << image_format->ext << std::endl; - if (!strncmp(image_format->ext, "aces", 3)) - { - aces_write(outputFile, output_scale, - image_buffer.width(), image_buffer.height(), image_buffer.depth(), - image_buffer.ptr(), image_format); - } - else if (!strncmp(image_format->ext, "exr", 3)) - { - exr_write(outputFile, output_scale, image_buffer, image_format, compression); - } - else if (!strncmp(image_format->ext, "adx", 3)) - { - dpx_write(outputFile, output_scale, image_buffer, image_format); - } - else if (!strncmp(image_format->ext, "dpx", 3)) - { - dpx_write(outputFile, output_scale, image_buffer, image_format); - } - else if (!strncmp(image_format->ext, "tiff", 3)) - { - tiff_write(outputFile, output_scale, image_buffer, image_format); - } - else - { - fprintf(stderr, "unable to write a %s file (unknown format).\n", image_format->ext); - exit(1); - } + if (!strncmp(image_format->ext, "aces", 3)) + { + aces_write(outputFile, output_scale, + image_buffer.width(), image_buffer.height(), image_buffer.depth(), + image_buffer.ptr(), image_format); + } + else if (!strncmp(image_format->ext, "exr", 3)) + { + exr_write(outputFile, output_scale, image_buffer, image_format, compression); + } + else if (!strncmp(image_format->ext, "adx", 3)) + { + dpx_write(outputFile, output_scale, image_buffer, image_format); + } + else if (!strncmp(image_format->ext, "dpx", 3)) + { + dpx_write(outputFile, output_scale, image_buffer, image_format); + } + else if (!strncmp(image_format->ext, "tiff", 3)) + { + tiff_write(outputFile, output_scale, image_buffer, image_format); + } + else + { + fprintf(stderr, "unable to write a %s file (unknown format).\n", image_format->ext); + exit(1); + } } diff --git a/lib/IlmCtl/CMakeLists.txt b/lib/IlmCtl/CMakeLists.txt index 3672a431..cc49ca62 100644 --- a/lib/IlmCtl/CMakeLists.txt +++ b/lib/IlmCtl/CMakeLists.txt @@ -1,5 +1,9 @@ include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" ) +if(WIN32) + add_definitions( -DOPENEXR_DLL ) +endif(WIN32) + add_library( IlmCtl ${DO_SHARED} CtlAddr.cpp CtlAlign.cpp @@ -22,7 +26,7 @@ add_library( IlmCtl ${DO_SHARED} ) target_link_libraries( IlmCtl ${IlmBase_LDFLAGS_OTHER} ) -target_link_libraries( IlmCtl Iex IlmThread Half ) +target_link_libraries( IlmCtl ${OpenEXR_LIBRARIES}) set_target_properties( IlmCtl PROPERTIES VERSION ${CTL_VERSION} diff --git a/lib/IlmCtl/CtlExc.cpp b/lib/IlmCtl/CtlExc.cpp index 233a7b7b..ce5a1ecc 100644 --- a/lib/IlmCtl/CtlExc.cpp +++ b/lib/IlmCtl/CtlExc.cpp @@ -53,9 +53,15 @@ /////////////////////////////////////////////////////////////////////////// #include -#include #include -#include +#include +#ifdef WIN32 +# ifndef va_copy +# define va_copy( a, b ) a = b +# endif +#else +# include +#endif #include namespace Ctl { @@ -87,7 +93,7 @@ void CtlExc::_explain(const char *text, va_list _ap) { operator=(ptr); } -CtlExc::CtlExc(const char *format, ...) throw() { +CtlExc::CtlExc(const char *format, ...) throw() : Iex::BaseExc() { va_list ap; va_start(ap, format); diff --git a/lib/IlmCtl/CtlExc.h b/lib/IlmCtl/CtlExc.h index 4a92650f..bce6a800 100644 --- a/lib/IlmCtl/CtlExc.h +++ b/lib/IlmCtl/CtlExc.h @@ -72,22 +72,22 @@ class CtlExc : public Iex::BaseExc { public: void _explain(const char *text, va_list ap); CtlExc(const char *format=0, ...) throw(); - CtlExc(const std::string &text) throw(): Iex::BaseExc(text) {}; - CtlExc(std::stringstream &text) throw(): Iex::BaseExc(text) {}; + CtlExc(const std::string &text) throw() : Iex::BaseExc(text) {}; + CtlExc(std::stringstream &text) throw() : Iex::BaseExc(text) {}; }; #define CTL_DEFINE_EXC(name, base) \ class name : public base \ { \ public: \ - name (const char* text=0, ...) throw() { \ + name(const char* text=0, ... ) throw() : base(text) { \ va_list ap; \ va_start(ap, text); \ _explain(text, ap); \ va_end(ap); \ }; \ - name (const std::string &text) throw(): base (text) {} \ - name (std::stringstream &text) throw(): base (text) {} \ + name(const std::string &text) throw(): base (text) {} \ + name(std::stringstream &text) throw(): base (text) {} \ }; diff --git a/lib/IlmCtl/CtlInterpreter.cpp b/lib/IlmCtl/CtlInterpreter.cpp index f22058e7..c051701a 100755 --- a/lib/IlmCtl/CtlInterpreter.cpp +++ b/lib/IlmCtl/CtlInterpreter.cpp @@ -59,6 +59,7 @@ // //----------------------------------------------------------------------------- + #include #include #include @@ -75,9 +76,12 @@ #include #ifdef WIN32 - #include #include #include + #include + #include + #define snprintf _snprintf + #define lrand48 rand #else #include #endif diff --git a/lib/IlmCtl/CtlLex.cpp b/lib/IlmCtl/CtlLex.cpp index 530a789c..f05b969d 100644 --- a/lib/IlmCtl/CtlLex.cpp +++ b/lib/IlmCtl/CtlLex.cpp @@ -1,55 +1,48 @@ /////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2013 Academy of Motion Picture Arts and Sciences +// +// Copyright (c) 2006 Academy of Motion Picture Arts and Sciences // ("A.M.P.A.S."). Portions contributed by others as indicated. // All rights reserved. // -// A worldwide, royalty-free, non-exclusive right to copy, modify, create -// derivatives, and use, in source and binary forms, is hereby granted, -// subject to acceptance of this license. Performance of any of the -// aforementioned acts indicates acceptance to be bound by the following -// terms and conditions: -// -// * Copies of source code, in whole or in part, must retain the -// above copyright notice, this list of conditions and the -// Disclaimer of Warranty. -// -// * Use in binary form must retain the above copyright notice, -// this list of conditions and the Disclaimer of Warranty in the -// documentation and/or other materials provided with the distribution. -// -// * Nothing in this license shall be deemed to grant any rights to -// trademarks, copyrights, patents, trade secrets or any other -// intellectual property of A.M.P.A.S. or any contributors, except -// as expressly stated herein. -// -// * Neither the name "A.M.P.A.S." nor the name of any other -// contributors to this software may be used to endorse or promote -// products derivative of or based on this software without express -// prior written permission of A.M.P.A.S. or the contributors, as -// appropriate. +// A world-wide, royalty-free, non-exclusive right to distribute, copy, +// modify, create derivatives, and use, in source and binary forms, is +// hereby granted, subject to acceptance of this license. Performance of +// any of the aforementioned acts indicates acceptance to be bound by the +// following terms and conditions: // -// This license shall be construed pursuant to the laws of the State of -// California, and any disputes related thereto shall be subject to the -// jurisdiction of the courts therein. -// -// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND -// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO -// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, -// 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. +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the Disclaimer of Warranty. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the Disclaimer of Warranty +// in the documentation and/or other materials provided with the +// distribution. +// +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except +// as expressly stated herein, and neither the name of A.M.P.A.S. +// nor of any other contributors to this software, may be used to +// endorse or promote products derived from this software without +// specific prior written permission of A.M.P.A.S. or contributor, +// as appropriate. +// +// This license shall be governed by the laws of the State of California, +// and subject to the jurisdiction of the courts therein. +// +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., ANY CONTRIBUTORS OR DISTRIBUTORS 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. // -// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY -// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER -// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY -// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER -// THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. /////////////////////////////////////////////////////////////////////////// @@ -64,6 +57,9 @@ #include #include #include +#include +#include +#include #include @@ -144,6 +140,341 @@ getLine (istream &is, string &str) } +// +// Helper functions for stringToDouble() +// + +void +convertMantissa (const char *&nextChar, double &mantissa, int &exponentBias) +{ + // + // Parse and convert the "mantissa" of our number, that is, the digits + // and the optional decimal point to the left of the 'e' or end the end + // of the string. (Examples: the mantissa in "-1.23e-45" is "1.23", and + // the mantissa in "123" is "123".) + // + // Convert the mantissa to a (potentially rather large) integer, m, and + // compute an "exponent bias," b, such that m*pow(10,b) yields the correct + // numerical value for the mantissa. For example "1.23" is converted to + // m = 123, b = -2. + // + // We ensure that m does not become larger than about 10/DBL_EPSILON, + // but we do allow b to become arbitrarily large. Once m is larger + // than 10/DBL_EPSILON the numerical result of multiplying m by 10 and + // adding another digit to it is no different than what we get from + // leaving m alone and adjusting the exponent bias instead. + // + + // + // Consume leading zeros, keep track of the decimal point. + // + + bool afterDecimalPoint = false; + mantissa = 0; + exponentBias = 0; + + while (*nextChar == '0') + ++nextChar; + + if (*nextChar == '.') + { + afterDecimalPoint = true; + ++nextChar; + + while (*nextChar == '0') + { + --exponentBias; + ++nextChar; + } + } + + // + // Consume remaining digits, again, keeping track of the decimal point. + // + + while (isdigit (*nextChar) || *nextChar == '.') + { + if (*nextChar == '.') + { + if (afterDecimalPoint) + break; + + afterDecimalPoint = true; + } + else + { + if (afterDecimalPoint) + { + if (mantissa <= 1 / DBL_EPSILON) + { + mantissa = mantissa * 10 + (*nextChar - '0'); + --exponentBias; + } + } + else + { + if (mantissa <= 1 / DBL_EPSILON) + mantissa = mantissa * 10 + (*nextChar - '0'); + else + ++exponentBias; + } + } + + ++nextChar; + } +} + + +void +convertExponent (const char *&nextChar, int &exponent) +{ + // + // Parse and convert the "exponent" of our number, that is, the digits + // to the right of the 'e' and an optional sign. (Example: the exponent + // in "-1.23e-45" is "45".) + // + // We do not allow the exponent to exceed INT_MAX. + // + + exponent = 0; + + while (isdigit (*nextChar)) + { + if (exponent <= INT_MAX / 10) + { + exponent = exponent * 10 + (*nextChar - '0'); + ++nextChar; + } + else + { + exponent = INT_MAX; + + while (isdigit (*nextChar)) + ++nextChar; + + return; + } + } +} + + +void +convertSignMantissaExponent + (const char *&nextChar, double &sign, double &mantissa, int &exponent) +{ + // + // Consume leading whitespace. + // + + while (isspace (*nextChar)) + ++nextChar; + + // + // Sign + // + + sign = 1; + + while (*nextChar == '+' || *nextChar == '-') + { + if (*nextChar == '-') + sign = -sign; + + ++nextChar; + } + + // + // Mantissa and exponent bias. + // + + int exponentBias; + convertMantissa (nextChar, mantissa, exponentBias); + + // + // Exponent sign and exponent. + // + + if (*nextChar == 'e' || *nextChar == 'E') + { + ++nextChar; + + int exponentSign = 1; + + while (*nextChar == '+' || *nextChar == '-') + { + if (*nextChar == '-') + exponentSign = -exponentSign; + + ++nextChar; + } + + convertExponent (nextChar, exponent); + exponent *= exponentSign; + } + else + { + exponent = 0; + } + + // + // Adjust the exponent by adding the exponent bias to it. + // If the correct result would overflow or underflow, then + // set the exponent INT_MAX or -INT_MAX respectively. + // + + if (exponent > 0) + { + if (exponentBias <= 0 || exponent <= INT_MAX - exponentBias) + exponent += exponentBias; + else + exponent = INT_MAX; + } + else + { + if (exponentBias >= 0 || exponent >= -INT_MAX - exponentBias) + exponent += exponentBias; + else + exponent = -INT_MAX; + } +} + + +double +pow10 (int n) +{ + // + // Compute pow(10,n), assuming that the calculation will not overflow. + // + + if (n < 0) + return 1 / pow10 (-n); + + assert (n <= DBL_MAX_10_EXP); + + double x = 1; + double y = 10; + + while (n > 0) + { + if (n & 1) + x *= y; + + y = y * y; + n >>= 1; + } + + return x; +} + + +double +mantissaTimesPow10OfExponent (double mantissa, int exponent) +{ + // + // Compute + // + // mantissa * pow(10,exponent) + // + // and return the correct result as long as it is representable + // as a double, even if pow(10,exponent) by itself would overflow + // or underflow. + // + + assert (mantissa >= 0); + + if (exponent > 0) + { + while (exponent > DBL_MAX_10_EXP) + { + double scale = pow10 (DBL_MAX_10_EXP); + + if (mantissa > DBL_MAX / scale) + return DBL_MAX; + + mantissa *= scale; + exponent -= DBL_MAX_10_EXP; + } + + double scale = pow10 (exponent); + + if (mantissa > DBL_MAX / scale) + return DBL_MAX; + + mantissa *= scale; + } + else + { + while (exponent < DBL_MIN_10_EXP) + { + mantissa *= pow10 (DBL_MIN_10_EXP); + exponent -= DBL_MIN_10_EXP; + + if (mantissa == 0) + return 0; + } + + mantissa *= pow10 (exponent); + } + + return mantissa; +} + + +double +stringToDouble (const char string[], const char **endptr) +{ + // + // stringToDouble() converts a null-terminated text string to a double- + // precision floating-point number. The string must consist of optional + // leading white space, followed by an optional '+' or '-' sign, a sequence + // of digits that may contain an optional decimal point, and an optional + // exponent. The exponent consists of an 'E' or 'e', followed by an + // optional '+' or '-' sign and a sequence of digits. + // + // Examples of valid strings: + // + // 0 + // 123 + // -0.03 + // +.576 + // 1.456e-10 + // 4e+5 + // + // Strings that do not fit the pattern indicated above are converted + // to 0.0. Text after the part of the string that represents the number + // is ignored. For example, "." and "hello" are converted to 0.0, and + // "15 rabbits" is converted to 15.0. + // + // If the number represented by the string is too large to be represented + // as a double-precision floating-point number, then stringToDouble() + // returns DBL_MAX, or -DBL_MAX, depending on the sign of the number. + // + // Note that there are some pathological cases such as writing 1.0 as "1" + // followed by 500 zeros and "e-500" ("100000...0000000e-500"), or writing + // 0.1 as "0." followed by 500 zeros and "1e500" ("0.00000...00000001e500"). + // Even though those should be rare in practice, stringToDouble() will + // produce the correct numerical result. However, stringToDouble() will + // fail and produce an incorrect result if the input string approches + // INT_MAX (about 2 billion) digits. + // + // If endptr is not null, then stringToDouble() sets *endptr to point to + // the first character after the part of the string that was converted + // to a double. + // + + double sign; + double mantissa; + int exponent; + + convertSignMantissaExponent (string, sign, mantissa, exponent); + + if (endptr) + *endptr = string; + + return sign * mantissaTimesPow10OfExponent (mantissa, exponent); +} + + } // namespace @@ -225,7 +556,7 @@ Lex::nextLine () inline bool Lex::atEndOfLine () const { - return _currentCharIndex >= (int)_currentLine.size(); + return _currentCharIndex >= _currentLine.size(); } @@ -620,7 +951,7 @@ Lex::getAtKeyword() int errorValue = -1; errorValue = strtol (b, &e, 0); - if (e - b != (int)_tokenStringValue.size()) + if (e - b != _tokenStringValue.size()) { printCurrentLine(); MESSAGE_LE (_lcontext, ERR_AT_SYNTAX, _currentLineNumber, @@ -755,7 +1086,7 @@ Lex::getIntOrFloatLiteral (bool decimalPointSeen) _tokenIntValue = strtol (b, &e, 0); - if (e - b != (int)_tokenStringValue.size()) + if (e - b != _tokenStringValue.size()) { _tokenIntValue = 0; @@ -825,11 +1156,11 @@ Lex::getIntOrFloatLiteral (bool decimalPointSeen) if (isFloat) { const char *b = _tokenStringValue.c_str(); - char *e; + const char *e; - _tokenFloatValue = strtod (b, &e); + _tokenFloatValue = stringToDouble (b, &e); - if (e - b != (int)_tokenStringValue.size()) + if (e - b != _tokenStringValue.size()) { _tokenFloatValue = 0; @@ -866,7 +1197,7 @@ Lex::getIntOrFloatLiteral (bool decimalPointSeen) _tokenIntValue = strtol (b, &e, 0); - if (e - b != (int)_tokenStringValue.size()) + if (e - b != _tokenStringValue.size()) { _tokenIntValue = 0; diff --git a/lib/IlmCtl/CtlLex.h b/lib/IlmCtl/CtlLex.h index 782d2bc5..f64a4517 100644 --- a/lib/IlmCtl/CtlLex.h +++ b/lib/IlmCtl/CtlLex.h @@ -68,6 +68,8 @@ #include #include + + namespace Ctl { @@ -83,7 +85,6 @@ class Lex Lex (LContext &lcontext); - //----------------------------------------------------------------- // Advance to the text token: // diff --git a/lib/IlmCtl/CtlStdType.cpp b/lib/IlmCtl/CtlStdType.cpp index b6aef15f..0a9495f1 100644 --- a/lib/IlmCtl/CtlStdType.cpp +++ b/lib/IlmCtl/CtlStdType.cpp @@ -53,6 +53,7 @@ /////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include diff --git a/lib/IlmCtl/CtlType.cpp b/lib/IlmCtl/CtlType.cpp index ea8ea8a1..0796e7ca 100644 --- a/lib/IlmCtl/CtlType.cpp +++ b/lib/IlmCtl/CtlType.cpp @@ -58,6 +58,7 @@ // //----------------------------------------------------------------------------- +#define _CRT_NO_VA_START_VALIDATION #include #include #include diff --git a/lib/IlmCtl/CtlTypeStorage.cpp b/lib/IlmCtl/CtlTypeStorage.cpp index 0519aee3..90bf87d0 100644 --- a/lib/IlmCtl/CtlTypeStorage.cpp +++ b/lib/IlmCtl/CtlTypeStorage.cpp @@ -59,12 +59,18 @@ // //----------------------------------------------------------------------------- +#define _CRT_NO_VA_START_VALIDATION #include #include #include #include #include -#include +#ifdef WIN32 +# include +# define strtof strtod +#else +# include +#endif #include #include #include diff --git a/lib/IlmCtlMath/CMakeLists.txt b/lib/IlmCtlMath/CMakeLists.txt index 96738cf8..a3c80a18 100644 --- a/lib/IlmCtlMath/CMakeLists.txt +++ b/lib/IlmCtlMath/CMakeLists.txt @@ -1,4 +1,10 @@ -include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/lib/IlmCtl" ) + +if(WIN32) + add_definitions( -DOPENEXR_DLL ) +endif(WIN32) + + +include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_BINARY_DIR}/lib/IlmCtl" ) add_library( IlmCtlMath ${DO_SHARED} CtlColorSpace.cpp diff --git a/lib/IlmCtlMath/CtlPointTree.h b/lib/IlmCtlMath/CtlPointTree.h index a604c9f9..f1088c16 100644 --- a/lib/IlmCtlMath/CtlPointTree.h +++ b/lib/IlmCtlMath/CtlPointTree.h @@ -1,54 +1,54 @@ /////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2013 Academy of Motion Picture Arts and Sciences +// Copyright (c) 2013 Academy of Motion Picture Arts and Sciences // ("A.M.P.A.S."). Portions contributed by others as indicated. // All rights reserved. -// +// // A worldwide, royalty-free, non-exclusive right to copy, modify, create -// derivatives, and use, in source and binary forms, is hereby granted, -// subject to acceptance of this license. Performance of any of the -// aforementioned acts indicates acceptance to be bound by the following +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following // terms and conditions: // -// * Copies of source code, in whole or in part, must retain the -// above copyright notice, this list of conditions and the +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the // Disclaimer of Warranty. // -// * Use in binary form must retain the above copyright notice, +// * Use in binary form must retain the above copyright notice, // this list of conditions and the Disclaimer of Warranty in the // documentation and/or other materials provided with the distribution. // -// * Nothing in this license shall be deemed to grant any rights to -// trademarks, copyrights, patents, trade secrets or any other -// intellectual property of A.M.P.A.S. or any contributors, except +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except // as expressly stated herein. // -// * Neither the name "A.M.P.A.S." nor the name of any other -// contributors to this software may be used to endorse or promote -// products derivative of or based on this software without express -// prior written permission of A.M.P.A.S. or the contributors, as +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as // appropriate. -// -// This license shall be construed pursuant to the laws of the State of -// California, and any disputes related thereto shall be subject to the +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the // jurisdiction of the courts therein. // -// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND -// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO -// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, -// 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 +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// 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. // -// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY -// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER -// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY -// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER // THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. /////////////////////////////////////////////////////////////////////////// @@ -60,7 +60,7 @@ // class PointTree<> // // This class implements a binary tree spacial partition -// for 3D points. The tree allows two kinds of queries: +// for 3D points. The tree allows two kinds of queries: // // - find all points within a given sphere // - find the n points that are closest to a given location @@ -70,13 +70,14 @@ #include #include #include +#include namespace Ctl { class PointTree { public: - + //----------------------------------------------------- // Constructor and destructor // @@ -85,11 +86,11 @@ class PointTree // up to the caller to make sure that the array remains // vaoid as long as the PointTree exists. //----------------------------------------------------- - + PointTree (const Imath::V3f *points, size_t numPoints, - size_t leafSize = 8, - size_t maxDepth = 150); + size_t leafSize = 8, + size_t maxDepth = 150); ~PointTree(); @@ -109,8 +110,8 @@ class PointTree //-------------------------------------------------------- void intersect (const Imath::V3f &point, - double radius, - std::vector &indices) const; + double radius, + std::vector &indices) const; //---------------------------------------------------- @@ -126,21 +127,21 @@ class PointTree //---------------------------------------------------- void nearestPoints (const Imath::V3f ¢er, - size_t numPoints, - std::vector &indices) const; + size_t numPoints, + std::vector &indices) const; private: struct Node { - Node () {_left = 0; _right = 0; _dataIndex = 0;} - ~Node () {delete _left; delete _right;} - - Node * _left; - Node * _right; - double _midValue; - size_t * _dataIndex; - size_t _dataSize; + Node () {_left = 0; _right = 0; _dataIndex = 0;} + ~Node () {delete _left; delete _right;} + + Node * _left; + Node * _right; + double _midValue; + size_t * _dataIndex; + size_t _dataSize; }; @@ -148,14 +149,14 @@ class PointTree { public: - int - operator() (const size_t &a, const size_t &b) - { - return points[a][dimension] < points[b][dimension]; - } + int + operator() (const size_t &a, const size_t &b) + { + return points[a][dimension] < points[b][dimension]; + } - size_t dimension; - const Imath::V3f *points; + size_t dimension; + const Imath::V3f *points; }; @@ -163,51 +164,51 @@ class PointTree { private: - Imath::V3f _center; - const Imath::V3f* _points; + Imath::V3f _center; + const Imath::V3f* _points; public: - CompareDistance (const Imath::V3f ¢er, const Imath::V3f *points) - { - _center = center; - _points = points; - } - - bool - operator() (size_t a, size_t b) - { - double al = (_points[a] - _center).length2(); - double bl = (_points[b] - _center).length2(); - - volatile double delta = fabs (al - bl); - const double eps = 2.0 * Imath::limits::epsilon(); - - // - // Impose strict weak ordering... if the lengths are the same, - // arbitrarily pick the one with the smallest index. - // - - if (delta < eps) - return a < b; - else - return al < bl; - } + CompareDistance (const Imath::V3f ¢er, const Imath::V3f *points) + { + _center = center; + _points = points; + } + + bool + operator() (size_t a, size_t b) + { + double al = (_points[a] - _center).length2(); + double bl = (_points[b] - _center).length2(); + + volatile double delta = fabs (al - bl); + const double eps = 2.0 * std::numeric_limits::epsilon(); + + // + // Impose strict weak ordering... if the lengths are the same, + // arbitrarily pick the one with the smallest index. + // + + if (delta < eps) + return a < b; + else + return al < bl; + } }; void intersect (Node *node, - const Imath::Box3f &box, - size_t dimension, - const Imath::V3f &point, - double radius, - std::vector &array) const; + const Imath::Box3f &box, + size_t dimension, + const Imath::V3f &point, + double radius, + std::vector &array) const; void split (Node *node, - size_t dimension, - size_t depth, - const Imath::Box3f &box, - size_t *array, - size_t arraySize); + size_t dimension, + size_t depth, + const Imath::Box3f &box, + size_t *array, + size_t arraySize); static double boxVolume (const Imath::Box3f &box); static double radiusOfSphereWithVolume (double volume); @@ -269,15 +270,15 @@ PointTree::rebuild() for (size_t i = _numPoints; i--;) { - _bbox.extendBy (_points[i]); - _indexArray[i] = i; + _bbox.extendBy (_points[i]); + _indexArray[i] = i; } _numNodes = 0; size_t dimension = _bbox.majorAxis(); if ( _topNode ) - delete _topNode; + delete _topNode; _topNode = new Node; _numNodes++; @@ -297,13 +298,13 @@ PointTree::split size_t arraySize) { if (_depth < depth) - _depth = depth; + _depth = depth; if (arraySize <= _leafSize || depth == _maxDepth) { - node->_dataIndex = array; - node->_dataSize = arraySize; - return; + node->_dataIndex = array; + node->_dataSize = arraySize; + return; } // @@ -342,43 +343,43 @@ PointTree::split if (leftArraySize) { - Imath::Box3f leftBox (box); - leftBox.max[dimension] = node->_midValue; - size_t nextDimension = leftBox.majorAxis(); - node->_left = new Node; - _numNodes++; - - split (node->_left, - nextDimension, - depth + 1, - leftBox, - leftArray, - leftArraySize); + Imath::Box3f leftBox (box); + leftBox.max[dimension] = node->_midValue; + size_t nextDimension = leftBox.majorAxis(); + node->_left = new Node; + _numNodes++; + + split (node->_left, + nextDimension, + depth + 1, + leftBox, + leftArray, + leftArraySize); } if (rightArraySize) { - Imath::Box3f rightBox (box); - rightBox.min[dimension] = node->_midValue; - size_t nextDimension = rightBox.majorAxis(); - node->_right = new Node; - _numNodes++; - - split (node->_right, - nextDimension, - depth + 1, - rightBox, - rightArray, - rightArraySize); + Imath::Box3f rightBox (box); + rightBox.min[dimension] = node->_midValue; + size_t nextDimension = rightBox.majorAxis(); + node->_right = new Node; + _numNodes++; + + split (node->_right, + nextDimension, + depth + 1, + rightBox, + rightArray, + rightArraySize); } node->_dataSize = 0; if (node->_left) - node->_dataSize += node->_left->_dataSize; + node->_dataSize += node->_left->_dataSize; if (node->_right) - node->_dataSize += node->_right->_dataSize; + node->_dataSize += node->_right->_dataSize; } @@ -404,61 +405,61 @@ PointTree::intersect { if (node->_dataIndex) { - double radius2 = radius * radius; - size_t index; + double radius2 = radius * radius; + size_t index; - for (size_t i = 0; i < node->_dataSize; i++) - { - index = node->_dataIndex[i]; - Imath::V3f vec = _points[index] - point; + for (size_t i = 0; i < node->_dataSize; i++) + { + index = node->_dataIndex[i]; + Imath::V3f vec = _points[index] - point; - if (vec.dot(vec) < radius2) - array.push_back(index); - } + if (vec.dot(vec) < radius2) + array.push_back(index); + } } else { - Imath::V3f rvec(radius); - - if (node->_left) - { - Imath::Box3f newBox(box); - newBox.max[dimension] = node->_midValue; - size_t nextDimension = newBox.majorAxis(); - Imath::Box3f tNewBox(newBox); - tNewBox.min -= rvec; - tNewBox.max += rvec; - - if (tNewBox.intersects (point)) - { - intersect (node->_left, - newBox, - nextDimension, - point, - radius, - array); - } - } - - if (node->_right) - { - Imath::Box3f newBox(box); - newBox.min[dimension] = node->_midValue; - size_t nextDimension = newBox.majorAxis(); - Imath::Box3f tNewBox(newBox); - tNewBox.min -= rvec; - tNewBox.max += rvec; - - if (tNewBox.intersects (point)) - { - intersect (node->_right, - newBox, - nextDimension, - point, - radius, - array); - } - } + Imath::V3f rvec(radius); + + if (node->_left) + { + Imath::Box3f newBox(box); + newBox.max[dimension] = node->_midValue; + size_t nextDimension = newBox.majorAxis(); + Imath::Box3f tNewBox(newBox); + tNewBox.min -= rvec; + tNewBox.max += rvec; + + if (tNewBox.intersects (point)) + { + intersect (node->_left, + newBox, + nextDimension, + point, + radius, + array); + } + } + + if (node->_right) + { + Imath::Box3f newBox(box); + newBox.min[dimension] = node->_midValue; + size_t nextDimension = newBox.majorAxis(); + Imath::Box3f tNewBox(newBox); + tNewBox.min -= rvec; + tNewBox.max += rvec; + + if (tNewBox.intersects (point)) + { + intersect (node->_right, + newBox, + nextDimension, + point, + radius, + array); + } + } } } @@ -472,101 +473,101 @@ PointTree::nearestPoints if (_topNode && numPoints > 0) { - if (_numPoints < numPoints) - { - // - // Special case -- the tree contains less than numPoints points. - // - - for (size_t i = 0; i < _numPoints; i++) - pointIndices.push_back (i); - } - else - { - // - // Find a subtree that contains the center and at least numPoints - // points. Based on the volume of the subtree's bounding box, - // make an "educated guess" for a search radius. - // - - const Node *node = _topNode; - Imath::Box3f bbox = _bbox; - - while (true) - { - if (node->_dataIndex) - { - // - // Node is a leaf. - // - - break; - } - - // - // Node is not a leaf. - // - - size_t dimension = bbox.majorAxis(); - - Imath::Box3f leftBbox (bbox); - leftBbox.max[dimension] = node->_midValue; - - Imath::Box3f rightBbox (bbox); - rightBbox.min[dimension] = node->_midValue; - - if (node->_left && - leftBbox.intersects (center) && - node->_left->_dataSize >= numPoints) - { - node = node->_left; - bbox = leftBbox; - } - else if (node->_right && - rightBbox.intersects (center) && - node->_right->_dataSize >= numPoints) - { - node = node->_right; - bbox = rightBbox; - } - else - { - break; - } - } - - double nodeVolume = boxVolume (bbox); - double searchVolume = 2 * nodeVolume * numPoints / node->_dataSize; - double searchRadius = radiusOfSphereWithVolume (searchVolume); - - // - // Find all points within the search radius. - // If we find less than numPoints points, increase - // the search radius (double the search volume). - // - - intersect (center, searchRadius, pointIndices); - - while (pointIndices.size() < numPoints) - { - searchRadius = radiusOfSphereWithTwiceVolume (searchRadius); - intersect (center, searchRadius, pointIndices); - } - - // - // Vector pointIndices now contains at least numPoints points, - // and probably not too many more. Partially sort the points - // so that the points closest to the center are in the vector's - // first numPoints positions. Then truncate the vector. - // - - std::nth_element (pointIndices.begin(), - pointIndices.begin() + (numPoints - 1), - pointIndices.end(), - CompareDistance (center, _points)); - - pointIndices.resize (numPoints); - } + if (_numPoints < numPoints) + { + // + // Special case -- the tree contains less than numPoints points. + // + + for (size_t i = 0; i < _numPoints; i++) + pointIndices.push_back (i); + } + else + { + // + // Find a subtree that contains the center and at least numPoints + // points. Based on the volume of the subtree's bounding box, + // make an "educated guess" for a search radius. + // + + const Node *node = _topNode; + Imath::Box3f bbox = _bbox; + + while (true) + { + if (node->_dataIndex) + { + // + // Node is a leaf. + // + + break; + } + + // + // Node is not a leaf. + // + + size_t dimension = bbox.majorAxis(); + + Imath::Box3f leftBbox (bbox); + leftBbox.max[dimension] = node->_midValue; + + Imath::Box3f rightBbox (bbox); + rightBbox.min[dimension] = node->_midValue; + + if (node->_left && + leftBbox.intersects (center) && + node->_left->_dataSize >= numPoints) + { + node = node->_left; + bbox = leftBbox; + } + else if (node->_right && + rightBbox.intersects (center) && + node->_right->_dataSize >= numPoints) + { + node = node->_right; + bbox = rightBbox; + } + else + { + break; + } + } + + double nodeVolume = boxVolume (bbox); + double searchVolume = 2 * nodeVolume * numPoints / node->_dataSize; + double searchRadius = radiusOfSphereWithVolume (searchVolume); + + // + // Find all points within the search radius. + // If we find less than numPoints points, increase + // the search radius (double the search volume). + // + + intersect (center, searchRadius, pointIndices); + + while (pointIndices.size() < numPoints) + { + searchRadius = radiusOfSphereWithTwiceVolume (searchRadius); + intersect (center, searchRadius, pointIndices); + } + + // + // Vector pointIndices now contains at least numPoints points, + // and probably not too many more. Partially sort the points + // so that the points closest to the center are in the vector's + // first numPoints positions. Then truncate the vector. + // + + std::nth_element (pointIndices.begin(), + pointIndices.begin() + (numPoints - 1), + pointIndices.end(), + CompareDistance (center, _points)); + + pointIndices.resize (numPoints); + } } } @@ -577,8 +578,8 @@ PointTree::boxVolume (const Imath::Box3f &box) double volume = 1; for (size_t i = 0; i < 3; ++i) - if (box.max[i] - box.min[i] > 0) - volume *= box.max[i] - box.min[i]; + if (box.max[i] - box.min[i] > 0) + volume *= box.max[i] - box.min[i]; return volume; } @@ -588,12 +589,12 @@ inline double PointTree::radiusOfSphereWithVolume (double volume) { #ifdef _WIN32 - if (volume <= 0) - return 0; - else - return (double) pow (0.238732 * volume, 1.0 / 3.0); + if (volume <= 0) + return 0; + else + return (double) pow (0.238732 * volume, 1.0 / 3.0); #else - return (double) cbrt (0.238732 * volume); + return (double) cbrt (0.238732 * volume); #endif } // 3/(4*pi) diff --git a/lib/IlmCtlSimd/CMakeLists.txt b/lib/IlmCtlSimd/CMakeLists.txt index 2ba792a2..16a35e30 100644 --- a/lib/IlmCtlSimd/CMakeLists.txt +++ b/lib/IlmCtlSimd/CMakeLists.txt @@ -1,14 +1,27 @@ include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/lib/IlmCtl" "${PROJECT_SOURCE_DIR}/lib/IlmCtlMath" ) +find_package( OpenEXR REQUIRED ) + + +if( WIN32 ) + FILE( COPY ${CMAKE_INSTALL_PREFIX}/bin/Imath-3_1.dll DESTINATION ${CMAKE_CURRENT_BINARY_DIR} ) +endif() + add_executable( halfExpLogTable halfExpLogTable.cpp ) -target_link_libraries( halfExpLogTable Half ) +target_link_libraries( halfExpLogTable ${IlmBase_LDFLAGS_OTHER} ) +target_link_libraries( halfExpLogTable ${OpenEXR_LIBRARIES} ) + add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/halfExpLogTable.h" - COMMAND halfExpLogTable "${CMAKE_CURRENT_BINARY_DIR}/halfExpLogTable.h" "${CMAKE_CURRENT_BINARY_DIR}/halfExpLog.h" - DEPENDS halfExpLogTable ) + COMMAND halfExpLogTable "${CMAKE_CURRENT_BINARY_DIR}/halfExpLogTable.h" "${CMAKE_CURRENT_BINARY_DIR}/halfExpLog.h" + DEPENDS halfExpLogTable ) include_directories( "${CMAKE_CURRENT_BINARY_DIR}" ) +if(WIN32) + add_definitions( -DOPENEXR_DLL ) +endif(WIN32) + add_library( IlmCtlSimd ${DO_SHARED} CtlSimdAddr.cpp CtlSimdFunctionCall.cpp @@ -33,7 +46,8 @@ add_library( IlmCtlSimd ${DO_SHARED} "${CMAKE_CURRENT_BINARY_DIR}/halfExpLogTable.h" ) -target_link_libraries( IlmCtlSimd IlmCtlMath IlmCtl ) +target_link_libraries( IlmCtlSimd ${IlmBase_LDFLAGS_OTHER} ) +target_link_libraries( IlmCtlSimd IlmCtlMath IlmCtl ${OPENEXR_LIBRARIES} ) set_target_properties( IlmCtlSimd PROPERTIES VERSION ${CTL_VERSION} diff --git a/lib/IlmCtlSimd/CtlSimdInst.cpp b/lib/IlmCtlSimd/CtlSimdInst.cpp index 4d329fcc..affd6d0f 100644 --- a/lib/IlmCtlSimd/CtlSimdInst.cpp +++ b/lib/IlmCtlSimd/CtlSimdInst.cpp @@ -68,7 +68,7 @@ namespace { #if 0 #include - #define debug(x) (cout << x << endl) + #define debug(x) (cerr << x << endl) #define debug_only(x) x #else #define debug(x) @@ -174,8 +174,8 @@ SimdInst::executePath (SimdBoolMask &mask, SimdXContext &xcontext) const xcontext.setLineNumber(inst->lineNumber()); - debug_only(cout << xcontext.lineNumber() << " "); - debug_only(cout << "fp=" << xcontext.stack().fp() + debug_only(cerr << xcontext.lineNumber() << " "); + debug_only(cerr << "fp=" << xcontext.stack().fp() << " sp=" << xcontext.stack().sp() << " "); debug_only(inst->print(0)); @@ -189,7 +189,7 @@ SimdInst::executePath (SimdBoolMask &mask, SimdXContext &xcontext) const REPLACE_EXC (e, "\n" << xcontext.fileName() << ":" << - inst->lineNumber() << ": " << e); + inst->lineNumber() << ": " << e.what()); throw e; } diff --git a/lib/IlmImfCtl/CMakeLists.txt b/lib/IlmImfCtl/CMakeLists.txt index 47563df4..5f7dcf9b 100644 --- a/lib/IlmImfCtl/CMakeLists.txt +++ b/lib/IlmImfCtl/CMakeLists.txt @@ -1,4 +1,9 @@ include_directories( "${CMAKE_CURRENT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/lib/IlmCtl" "${PROJECT_SOURCE_DIR}/lib/IlmCtlMath" "${PROJECT_SOURCE_DIR}/lib/IlmCtlSimd" ) + +if(WIN32) + add_definitions( -DOPENEXR_DLL ) +endif(WIN32) + include_directories( ${OpenEXR_INCLUDE_DIRS} ) link_directories( ${OpenEXR_LIBRARY_DIRS} ) @@ -7,7 +12,7 @@ add_library( IlmImfCtl ${DO_SHARED} ImfCtlCopyFunctionArg.cpp ) -target_link_libraries( IlmImfCtl IlmCtl IlmImf Iex IlmThread Half ) +target_link_libraries( IlmImfCtl IlmCtl ${OpenEXR_LIBRARIES} ) install( FILES ImfCtlApplyTransforms.h DESTINATION include/OpenEXR ) diff --git a/lib/IlmImfCtl/ImfCtlApplyTransforms.cpp b/lib/IlmImfCtl/ImfCtlApplyTransforms.cpp index 4f84ea7e..cf079917 100644 --- a/lib/IlmImfCtl/ImfCtlApplyTransforms.cpp +++ b/lib/IlmImfCtl/ImfCtlApplyTransforms.cpp @@ -60,6 +60,12 @@ // //----------------------------------------------------------------------------- +#include +#define __STDC_FORMAT_MACROS +#define __STDC_LIMIT_MACROS +#include + + #include #include #include @@ -69,6 +75,10 @@ #include #include +#if defined(_WIN32) || defined(_WIN64) +# include +#endif + using namespace std; using namespace Iex; using namespace Imath; @@ -263,8 +273,9 @@ callFunctions // // Call the function // - + debug( "callFunction with numSamples = " << numSamples ); func->callFunction (numSamples); + debug( "calledFunction with numSamples = " << numSamples ); // // Return output argument values to the caller. @@ -423,7 +434,24 @@ CallFunctionsTask::execute() FunctionList funcs; for (size_t i = 0; i < _transformNames.size(); ++i) - funcs.push_back (_interpreter.newFunctionCall (_transformNames[i])); + { + FunctionCallPtr fn; + try + { + fn = _interpreter.newFunctionCall( std::string("main") ); + funcs.push_back( fn ); + } + catch (const Iex::ArgExc &e) + { + // XXX CTL library needs to be changed so that we have a better + // XXX 'function not exists' exception. + } + + if ( fn.refcount() == 0 ) + { + funcs.push_back (_interpreter.newFunctionCall (_transformNames[i])); + } + } // // Repeatedly call the transform functions, breaking the @@ -481,7 +509,7 @@ applyTransforms // for (size_t i = 0; i < transformNames.size(); ++i) - interpreter.loadModule (transformNames[i]); + interpreter.loadModule(transformNames[i]); // // Determine how many samples we will process. diff --git a/lib/IlmImfCtl/ImfCtlCopyFunctionArg.cpp b/lib/IlmImfCtl/ImfCtlCopyFunctionArg.cpp index 45702df5..7fcc472d 100644 --- a/lib/IlmImfCtl/ImfCtlCopyFunctionArg.cpp +++ b/lib/IlmImfCtl/ImfCtlCopyFunctionArg.cpp @@ -315,11 +315,12 @@ copyFunctionArg y += 1; x = transformWindow.min.x; } + } break; - case Imf::FLOAT: + case Imf::FLOAT: if (!src->type().cast()) throwDstSliceTypeMismatch (src, "FLOAT"); diff --git a/lib/dpx/CMakeLists.txt b/lib/dpx/CMakeLists.txt index c8be26e1..df66d1d5 100644 --- a/lib/dpx/CMakeLists.txt +++ b/lib/dpx/CMakeLists.txt @@ -11,3 +11,8 @@ add_library( ctldpx dpx_rw.cc ) +if( WIN32 ) + add_definitions( -DIMATH_DLL -DOPENEXR_DLL ) +endif() + +target_link_libraries( ctldpx ${OPENEXR_LIBRARIES} ${IlmBase_LIBRARIES} ) diff --git a/lib/dpx/dpx.hh b/lib/dpx/dpx.hh index 02ae8331..dcb3b8aa 100644 --- a/lib/dpx/dpx.hh +++ b/lib/dpx/dpx.hh @@ -1,54 +1,54 @@ /////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2013 Academy of Motion Picture Arts and Sciences +// Copyright (c) 2013 Academy of Motion Picture Arts and Sciences // ("A.M.P.A.S."). Portions contributed by others as indicated. // All rights reserved. -// +// // A worldwide, royalty-free, non-exclusive right to copy, modify, create -// derivatives, and use, in source and binary forms, is hereby granted, -// subject to acceptance of this license. Performance of any of the -// aforementioned acts indicates acceptance to be bound by the following +// derivatives, and use, in source and binary forms, is hereby granted, +// subject to acceptance of this license. Performance of any of the +// aforementioned acts indicates acceptance to be bound by the following // terms and conditions: // -// * Copies of source code, in whole or in part, must retain the -// above copyright notice, this list of conditions and the +// * Copies of source code, in whole or in part, must retain the +// above copyright notice, this list of conditions and the // Disclaimer of Warranty. // -// * Use in binary form must retain the above copyright notice, +// * Use in binary form must retain the above copyright notice, // this list of conditions and the Disclaimer of Warranty in the // documentation and/or other materials provided with the distribution. // -// * Nothing in this license shall be deemed to grant any rights to -// trademarks, copyrights, patents, trade secrets or any other -// intellectual property of A.M.P.A.S. or any contributors, except +// * Nothing in this license shall be deemed to grant any rights to +// trademarks, copyrights, patents, trade secrets or any other +// intellectual property of A.M.P.A.S. or any contributors, except // as expressly stated herein. // -// * Neither the name "A.M.P.A.S." nor the name of any other -// contributors to this software may be used to endorse or promote -// products derivative of or based on this software without express -// prior written permission of A.M.P.A.S. or the contributors, as +// * Neither the name "A.M.P.A.S." nor the name of any other +// contributors to this software may be used to endorse or promote +// products derivative of or based on this software without express +// prior written permission of A.M.P.A.S. or the contributors, as // appropriate. -// -// This license shall be construed pursuant to the laws of the State of -// California, and any disputes related thereto shall be subject to the +// +// This license shall be construed pursuant to the laws of the State of +// California, and any disputes related thereto shall be subject to the // jurisdiction of the courts therein. // -// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND -// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO -// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, -// 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 +// Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO +// EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY, +// 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. // -// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY -// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER -// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY -// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER +// WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY +// SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER +// RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY +// COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER // THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. /////////////////////////////////////////////////////////////////////////// @@ -84,544 +84,544 @@ struct rwinfo; }; struct dpx { - // This class can read and write DPX 1.0, 2.0, and 3.0 files (in so - // far as the DPX 3.0 specification is complete). It should have no - // difficulty reading any extant DPX file, and can write all common - // variants of DPX 1.0/2.0 and all reasonable variants of DPX 3.0. - // Please see the 'compliance' member (below) for details on how to - // change this behavior. - // - // Fields marked with a '*' have some additional notes on them towards - // the end of the include file. - // - // Fields below marked with a '**' indicate fields that are - // synthesized (on reads) from the character array header field - // they are associated with. If the associated character array field - // has not been set (i.e. first character is a numeric 0) on write, - // then the field is decomposed back into a character array. - public: // specification field number - uint32_t magic; // 1 * - uint32_t data_offset; // 2 * - char header_version[9]; // 3 * - uint32_t total_file_size; // 4 - uint32_t ditto_key; // 5 * - uint32_t generic_header_length; // 6 - uint32_t industry_header_length; // 7 - uint32_t user_header_length; // 8 - - char filename[101]; // 9 - char creation_time[25]; // 10 - struct tm creation_time_tm; // 10a ** - char creator[101]; // 12 (no field 11 in dpx spec) - char project_name[201]; // 13 - char copyright[201]; // 14 - uint32_t encryption_key; // 15 * - - // skip 104 bytes // 16 - - uint16_t image_orientation; // 17 - uint16_t number_of_elements; // 18 - uint32_t pixels_per_line; // 19 - uint32_t lines_per_element; // 20 - - struct element_t { - friend class dpxi::rwinfo; - friend class dpx; - uint32_t data_sign; // 21.1 * - uint32_t ref_low_data_code; // 21.2 * - float32_t ref_low_quantity; // 21.3 * - uint32_t ref_high_data_code; // 21.4 * - float32_t ref_high_quantity; // 21.5 * - uint8_t descriptor; // 21.6 * - uint8_t transfer_characteristic; // 21.7 * - uint8_t colorimetric_characteristic; // 21.8 * - uint8_t bits_per_sample; // 21.9 * - uint16_t packing; // 21.10 * - uint16_t encoding; // 21.11 * - uint32_t offset_to_data; // 21.12 - uint32_t eol_padding; // 21.13 * - uint32_t eoi_padding; // 21.14 * - char description[33]; // 21.15 - - private: - uint16_t actual_packing; // see dpx_validate.cc - } elements[8]; // 21-28 - - // skip 52 bytes // 29 - - uint32_t x_offset; // 30 * - uint32_t y_offset; // 31 * - float32_t x_center; // 32 * - float32_t y_center; // 33 * - uint32_t x_origional_size; // 34 * - uint32_t y_origional_size; // 35 * - - char source_filename[101]; // 36 - char source_creation_time[25]; // 37 - struct tm source_creation_time_tm; // 37a ** - char input_device[33]; // 38 - char input_device_serial_number[33]; // 39 - - uint16_t xl_border_validity; // 40a - uint16_t xr_border_validity; // 40b - uint16_t yt_border_validity; // 40c - uint16_t yb_border_validity; // 40d - uint32_t horizonal_par; // 41a - uint32_t vertical_par; // 41b - - float32_t x_scanned_size; // 42.1 - float32_t y_scanned_size; // 42.2 - - // skip 20 bytes // 42.3 - - // film information header... - char keycode_film_id[3]; // 43 - char keycode_film_type_char[3]; // 44 - char keycode_perf_offset_char[3]; // 45 * - char keycode_prefix[7]; // 47 (no field 46 in dpx) - char keycode_count_char[5]; // 48 - - char format[33]; // 49 - uint32_t frame_position_in_sequence; // 50 - uint32_t sequence_length; // 51 - uint32_t held_count; // 52 - float32_t frame_rate; // 53 - float32_t shutter_angle; // 54 - char frame_attribute[33]; // 55 - char frame_slate_info[101]; // 56 - float32_t film_gague; // 57.0 * - uint8_t film_orientation; // 57.1 * - uint8_t film_perf_per_foot; // 57.2 * - uint8_t film_perf_per_frame; // 57.3 * - char film_manufacturer[17]; // 57.4 * - char film_stock_name[17]; // 57.5 * - struct keycode { - //enum film_id_type_kind { - // numeric=0, - // alpha=1 - //} film_id_type_kind; - uint8_t id; - uint8_t type; - float32_t film_gague; - enum film_orientation_e { - vistavision=1, - horizontal=1, - normal=0, - vertical=0 - }; - uint8_t perf_per_frame; - uint8_t perf_per_foot; - std::string manufacturer; - std::string stock_number; - uint32_t prefix; - uint16_t foot; - uint8_t perf; - // Add perf arithmatic operations... - } keycode; // 57a ** - - // skip 21 bytes (less than original, taken up by 57.x above) - - // video information header... - uint32_t smpte_timecode; // 58 - uint32_t smpte_userbits; // 59 - uint8_t interlace; // 60 - uint8_t field_number; // 61 - uint8_t video_standard; // 62 - // skip 1 byte // 63 - float32_t horizontal_sampling_rate; // 64 - float32_t vertical_sampling_rate; // 65 - float32_t temporal_sampling_rate; // 66 - float32_t time_offset_sync_to_first_pixel; // 67 - float32_t gamma; // 68 - float32_t black_level_code; // 69 - float32_t black_gain; // 70 - float32_t breakpoint; // 71 - float32_t white_level_code; // 72 - float32_t integration_time; // 73 - // skip 76 bytes // 74 - - // we should be at byte 2048 at this point... - char user_id[33]; // 75 - - // end of header - - // Set on read() to either little_endian or big_endian based on - // the file byte order. Used on write to determine if bytes - // are to be written either in the native mode (0), always swapped (1), - // swapped if not on a little endian architecture (2), swapped if - // not on a big endian architecture (3). - // - // It is strongly suggested that this value be set to 'big_endian' - // for all writes, since Cinepaint can only deal with network order - // (big endian) dpx files. - enum endian_mode_e { - default_endian_mode=0, - native=1, - swapped=2, - little_endian=3, - big_endian=4, - } endian_mode; - - // This field is used to control any alternate interpretation - // of fields that may need to happen to read a file (or write a - // compatible file). On class construction this has a value of - // 0 (automatic). - // - enum compliance_e { - automatic =0, - dpx1 =0x10000000, - dpx3 =0x20000000, - } compliance; - - // Some helper functions to determine if a field is 'NULL' or - // to set a field to NULL. - static bool isnull(uint64_t v); - static bool isnull(uint32_t v); - static bool isnull(uint16_t v); - static bool isnull(uint8_t v); - static bool isnull(float32_t v); - - static void nullify(uint16_t *v); - static void nullify(uint8_t *v); - static void nullify(uint32_t *v); - static void nullify(uint64_t *v); - static void nullify(float32_t *v); - - // mark all fields as NULL. - void clear(void); - - private: - bool _need_byteswap; - friend class dpxi::rwinfo; - std::ostream *current_ostream; - compliance_e current_compliance; - endian_mode_e current_endian_mode; - - std::istream::streampos header_start; - - public: - virtual ~dpx(); - dpx(); - - // read and write only the header... - void read(std::istream *io); - void write(std::ostream *io); - - static bool check_magic(std::istream *io); - - // The framebuffer (fb) class that we use for putting image - // information into (and pulling out of) the file using the - // read(...) and write(...) methods. We can't use Imf::Array2D - // because that is part of the openexr libary, and we don't - // want a dependency on openexr for ctl (we *do* have a - // dependency on ilmbase, but that's OK). - // - template - class fb { - private: - T *_data; - uint32_t _width; - uint32_t _height; - uint32_t _depth; - uint64_t _length; - - public: - fb(); - ~fb(); - - void init(uint32_t width, uint32_t height, uint32_t depth); - - uint32_t width(void) const; - uint32_t height(void) const; - uint32_t depth(void) const; - - // the total number of bytes of storage - uint64_t length(void) const; - - // The total number of pixels - uint64_t pixels(void) const; - - // The total number of samples - uint64_t count(void) const; - - // Takes the stored pixels and treats them as if they - // were in the format described by the descriptor parameter - // (i.e. header field 21.6), and then move things about so - // the pixels are then ordered in a standard RGB(A) - // (or Y(A)) format. Optionally this will remove the alpha - // channel (set descriptor==0 if the data has already been - // formatted into RGBA or YA). - void swizzle(uint8_t descriptor, bool squish_alpha); - - // Indicates if the data has an alpha channel. - bool alpha() const; - // Set the alpha channel to the specified value (creates - // alpha channel if it does not exist). - void alpha(const T &value); - - T *ptr(void); - const T *ptr(void) const; - operator T *(); - operator const T *() const; - }; - - // Exception classes... - class exception : std::exception {}; - class invalid : exception {}; - class outofrange : exception {}; - class badtemplate : exception {}; - - // - // These implicitly call read(std::istream *i); to get a - // copy of the header. - // - // If the file's packing or bpp (or whatever...) is sufficiently - // foreign that we can't handle it, we will thow an 'invalid' - // exception. - // - // If the parameter element is out of range for the image (i.e. - // greater than or equal to 'number_of_elements' then an - // exception will be thrown. - // - enum intmode_e { - normal=0, - unformatted=1 - }; - void read(std::istream *io, uint8_t element, fb *buffer, - float64_t scale=0.0); - void read(std::istream *io, uint8_t element, fb *buffer, - float64_t scale=0.0); - void read(std::istream *io, uint8_t element, fb *buffer, - float64_t scale=0.0); - void read(std::istream *io, uint8_t element, fb *buffer, - float64_t scale=0.0, intmode_e mode=normal); - void read(std::istream *io, uint8_t element, fb *buffer, - float64_t scale=0.0, intmode_e mode=normal); - void read(std::istream *io, uint8_t element, fb *buffer, - float64_t scale=0.0, intmode_e mode=normal); - void read(std::istream *io, uint8_t element, fb *buffer, - float64_t scale=0.0, intmode_e mode=normal); - - // - // If not filled out ahead of time (i.e. have 'null' values associated - // with them), then the following fields will be set based on - // the version of the write method called. The defaults chosen are - // affected by the value of the 'compliance' field (described above). - // If compliance is set to 'automatic', then it is silently changed - // on first write to 'dpx1'. - // - // Common across all values of 'compliance': - // - // field default - // ------ ---------------------------------------------------------- - // 17 0 (pixels arranged left to right, top to bottom). - // 19 width of provided framebuffer - // 20 height of provided framebuffer - // 21.9 sizeof()*8 - // 21.1 (see below) - // 21.6 based on depth of framebuffer: - // depth descriptor - // ----- ----------------------------- - // 1 6 (Luminance) - // 2 158 (Luminance Alpha) (proposed) (*) - // 3 50 (RGB) - // 4 51 (RGBA) - // 5 153 (user defined 5 channel image) - // 6 154 (user defined 6 channel image) - // 7 155 (user defined 7 channel image) - // 8 156 (user defined 8 channel image) - // 21.7 1 if bits_per_sample==10, otherwise 2 - // 21.8 set equal to 21.7 (transfer characteristic) - // 21.10 (**)(packing) - // vaheader field valubits_per_sample, packing, - // descriptor, colorimetric_characteristic, transfer_characteristic, - // and offset_to_data will have reasonable default values placed - // in them by the write(...) method. The default values are determined - // on via the following scheme: - // - // - // IMPORTANT NOTE: Unlike the read(...) methods, the write methods - // presume that the interleaved data in the framebuffer is in the - // same order as the descriptor. - // - // All of these fields do not need - // to be filled out prior to calling write(...), , defaults will only be used as needed, colorimetric, and and elements[n].offset_to_data will have - // reasonable defaults set based on the number of channels in the - // framebuffer to write, and the type of the framebuffer. - // - // If there is a reasonable disconnect between the are not specified (i.e. - // are not all 0xff) then appropriate values will be selected - // based on the type provided in the frame buffer. - // If values are provided and do not match the framebuffer type - // then a warning will be posted (see below) and an attempt will - // be made to perform a conversion. If no conversion can be - // performed then an exception is thrown. - // Specifying the elements[n].offset_to_data is particularly - // dangerous as it will will be used without any sort of sanity - // checking and you can easily overwrite critical parts of your - // file. - // - // The number_of_elements value *must* be set prior to the first - // call to write. Failure to do this will cause an exception. - // - // The compliance field (above) must also be set prior to the - // first call/ to write. - // - // Elements should be written (preferably in order), after the - // last element has been written the header should be written. - // - // Like all of the read(...) methods, this will rewind the osream - // to the point it was at when the write(...) method was called. - // - void write(std::ostream *o, uint8_t element, - const fb &buffer, float64_t scale=0.0); - void write(std::ostream *o, uint8_t element, - const fb &buffer, float64_t scale=0.0); - void write(std::ostream *o, uint8_t element, - const fb &buffer, float64_t scale=0.0); - void write(std::ostream *o, uint8_t element, - const fb &buffer, float64_t scale=0.0, - intmode_e mode=normal); - void write(std::ostream *o, uint8_t element, - const fb &buffer, float64_t scale=0.0, - intmode_e mode=normal); - void write(std::ostream *o, uint8_t element, - const fb &buffer, float64_t scale=0.0, - intmode_e mode=normal); - void write(std::ostream *o, uint8_t element, - const fb &buffer, float64_t scale=0.0, - intmode_e mode=normal); - - // Can perform pretty much perform every imaginable conversion - // between two types. While there are a number of functions, they - // all eventually call the same method at the base of things, and - // the variants are to give slightly cleaner interfaces. - // - // The current interface only supports the following types (as either - // inputs and outputs): - // uint8_t (unsigned char) - // uint16_t (unsigned short) - // uint32_t (unsigned int) - // uint64_t (unsigned long long int) - // float16_t (half) - // float32_t (float) - // float64_t (double) - // - // Adding support for signed types is left as an excercise to the - // user. - // - // The parameter meanings are identical across all functions. If - // you are calling a function variant *without* the parameter, it - // defaults to a zero value (the behavior is described below). - // - // O template parameter that is the output type. - // I template parameter that is the input type. - // isb input significant bits, only used when then input type - // is an integer type. Will cause the input to be clipped - // from 0 to (1< - static void convert(O *o, const I *i, uint64_t count); - template - static void convert(O *o, const I *i, float64_t scale, uint64_t count); - template - static void convert(O *o, uint8_t osb, const I *i, uint64_t count); - template - static void convert(O *o, uint8_t osb, const I *i, float64_t scale, - uint64_t count); - template - static void convert(O *o, const I *i, uint8_t isb, uint64_t count); - template - static void convert(O *o, const I *i, uint8_t isb, float64_t scale, - uint64_t count); - template - static void convert(O *o, uint8_t osb, const I *i, uint8_t isb, - uint64_t count); - // This is the actual function that does the work. All of the others - // just fill out default values... - template - static void convert(O *o, uint8_t osb, const I *i, uint8_t isb, - float64_t scale, uint64_t count); - - - // Some static methods to take de-enumerate some of the - // header values. - static std::string smpte_timecode_to_string(uint32_t tc); - static std::string colormetric_to_string(uint8_t id); - static std::string transfer_to_string(uint8_t id); - static std::string video_to_string(uint8_t id); - static std::string encoding_to_string(uint8_t id); - static std::string packing_to_string(uint8_t id); - static std::string bits_per_sample_to_string(uint8_t id); - static std::string orientation_to_string(uint8_t id); - static std::string descriptor_to_string(uint8_t id); + // This class can read and write DPX 1.0, 2.0, and 3.0 files (in so + // far as the DPX 3.0 specification is complete). It should have no + // difficulty reading any extant DPX file, and can write all common + // variants of DPX 1.0/2.0 and all reasonable variants of DPX 3.0. + // Please see the 'compliance' member (below) for details on how to + // change this behavior. + // + // Fields marked with a '*' have some additional notes on them towards + // the end of the include file. + // + // Fields below marked with a '**' indicate fields that are + // synthesized (on reads) from the character array header field + // they are associated with. If the associated character array field + // has not been set (i.e. first character is a numeric 0) on write, + // then the field is decomposed back into a character array. + public: // specification field number + uint32_t magic; // 1 * + uint32_t data_offset; // 2 * + char header_version[9]; // 3 * + uint32_t total_file_size; // 4 + uint32_t ditto_key; // 5 * + uint32_t generic_header_length; // 6 + uint32_t industry_header_length; // 7 + uint32_t user_header_length; // 8 + + char filename[101]; // 9 + char creation_time[25]; // 10 + struct tm creation_time_tm; // 10a ** + char creator[101]; // 12 (no field 11 in dpx spec) + char project_name[201]; // 13 + char copyright[201]; // 14 + uint32_t encryption_key; // 15 * + + // skip 104 bytes // 16 + + uint16_t image_orientation; // 17 + uint16_t number_of_elements; // 18 + uint32_t pixels_per_line; // 19 + uint32_t lines_per_element; // 20 + + struct element_t { + friend class dpxi::rwinfo; + friend class dpx; + uint32_t data_sign; // 21.1 * + uint32_t ref_low_data_code; // 21.2 * + float32_t ref_low_quantity; // 21.3 * + uint32_t ref_high_data_code; // 21.4 * + float32_t ref_high_quantity; // 21.5 * + uint8_t descriptor; // 21.6 * + uint8_t transfer_characteristic; // 21.7 * + uint8_t colorimetric_characteristic; // 21.8 * + uint8_t bits_per_sample; // 21.9 * + uint16_t packing; // 21.10 * + uint16_t encoding; // 21.11 * + uint32_t offset_to_data; // 21.12 + uint32_t eol_padding; // 21.13 * + uint32_t eoi_padding; // 21.14 * + char description[33]; // 21.15 + + private: + uint16_t actual_packing; // see dpx_validate.cc + } elements[8]; // 21-28 + + // skip 52 bytes // 29 + + uint32_t x_offset; // 30 * + uint32_t y_offset; // 31 * + float32_t x_center; // 32 * + float32_t y_center; // 33 * + uint32_t x_origional_size; // 34 * + uint32_t y_origional_size; // 35 * + + char source_filename[101]; // 36 + char source_creation_time[25]; // 37 + struct tm source_creation_time_tm; // 37a ** + char input_device[33]; // 38 + char input_device_serial_number[33]; // 39 + + uint16_t xl_border_validity; // 40a + uint16_t xr_border_validity; // 40b + uint16_t yt_border_validity; // 40c + uint16_t yb_border_validity; // 40d + uint32_t horizonal_par; // 41a + uint32_t vertical_par; // 41b + + float32_t x_scanned_size; // 42.1 + float32_t y_scanned_size; // 42.2 + + // skip 20 bytes // 42.3 + + // film information header... + char keycode_film_id[3]; // 43 + char keycode_film_type_char[3]; // 44 + char keycode_perf_offset_char[3]; // 45 * + char keycode_prefix[7]; // 47 (no field 46 in dpx) + char keycode_count_char[5]; // 48 + + char format[33]; // 49 + uint32_t frame_position_in_sequence; // 50 + uint32_t sequence_length; // 51 + uint32_t held_count; // 52 + float32_t frame_rate; // 53 + float32_t shutter_angle; // 54 + char frame_attribute[33]; // 55 + char frame_slate_info[101]; // 56 + float32_t film_gague; // 57.0 * + uint8_t film_orientation; // 57.1 * + uint8_t film_perf_per_foot; // 57.2 * + uint8_t film_perf_per_frame; // 57.3 * + char film_manufacturer[17]; // 57.4 * + char film_stock_name[17]; // 57.5 * + struct keycode { + //enum film_id_type_kind { + // numeric=0, + // alpha=1 + //} film_id_type_kind; + uint8_t id; + uint8_t type; + float32_t film_gague; + enum film_orientation_e { + vistavision=1, + horizontal=1, + normal=0, + vertical=0 + }; + uint8_t perf_per_frame; + uint8_t perf_per_foot; + std::string manufacturer; + std::string stock_number; + uint32_t prefix; + uint16_t foot; + uint8_t perf; + // Add perf arithmatic operations... + } keycode; // 57a ** + + // skip 21 bytes (less than original, taken up by 57.x above) + + // video information header... + uint32_t smpte_timecode; // 58 + uint32_t smpte_userbits; // 59 + uint8_t interlace; // 60 + uint8_t field_number; // 61 + uint8_t video_standard; // 62 + // skip 1 byte // 63 + float32_t horizontal_sampling_rate; // 64 + float32_t vertical_sampling_rate; // 65 + float32_t temporal_sampling_rate; // 66 + float32_t time_offset_sync_to_first_pixel; // 67 + float32_t gamma; // 68 + float32_t black_level_code; // 69 + float32_t black_gain; // 70 + float32_t breakpoint; // 71 + float32_t white_level_code; // 72 + float32_t integration_time; // 73 + // skip 76 bytes // 74 + + // we should be at byte 2048 at this point... + char user_id[33]; // 75 + + // end of header + + // Set on read() to either little_endian or big_endian based on + // the file byte order. Used on write to determine if bytes + // are to be written either in the native mode (0), always swapped (1), + // swapped if not on a little endian architecture (2), swapped if + // not on a big endian architecture (3). + // + // It is strongly suggested that this value be set to 'big_endian' + // for all writes, since Cinepaint can only deal with network order + // (big endian) dpx files. + enum endian_mode_e { + default_endian_mode=0, + native=1, + swapped=2, + little_endian=3, + big_endian=4, + } endian_mode; + + // This field is used to control any alternate interpretation + // of fields that may need to happen to read a file (or write a + // compatible file). On class construction this has a value of + // 0 (automatic). + // + enum compliance_e { + automatic =0, + dpx1 =0x10000000, + dpx3 =0x20000000, + } compliance; + + // Some helper functions to determine if a field is 'NULL' or + // to set a field to NULL. + static bool isnull(uint64_t v); + static bool isnull(uint32_t v); + static bool isnull(uint16_t v); + static bool isnull(uint8_t v); + static bool isnull(float32_t v); + + static void nullify(uint16_t *v); + static void nullify(uint8_t *v); + static void nullify(uint32_t *v); + static void nullify(uint64_t *v); + static void nullify(float32_t *v); + + // mark all fields as NULL. + void clear(void); + + private: + bool _need_byteswap; + friend class dpxi::rwinfo; + std::ostream *current_ostream; + compliance_e current_compliance; + endian_mode_e current_endian_mode; + + std::streampos header_start; + + public: + virtual ~dpx(); + dpx(); + + // read and write only the header... + void read(std::istream *io); + void write(std::ostream *io); + + static bool check_magic(std::istream *io); + + // The framebuffer (fb) class that we use for putting image + // information into (and pulling out of) the file using the + // read(...) and write(...) methods. We can't use Imf::Array2D + // because that is part of the openexr libary, and we don't + // want a dependency on openexr for ctl (we *do* have a + // dependency on ilmbase, but that's OK). + // + template + class fb { + private: + T *_data; + uint32_t _width; + uint32_t _height; + uint32_t _depth; + uint64_t _length; + + public: + fb(); + ~fb(); + + void init(uint32_t width, uint32_t height, uint32_t depth); + + uint32_t width(void) const; + uint32_t height(void) const; + uint32_t depth(void) const; + + // the total number of bytes of storage + uint64_t length(void) const; + + // The total number of pixels + uint64_t pixels(void) const; + + // The total number of samples + uint64_t count(void) const; + + // Takes the stored pixels and treats them as if they + // were in the format described by the descriptor parameter + // (i.e. header field 21.6), and then move things about so + // the pixels are then ordered in a standard RGB(A) + // (or Y(A)) format. Optionally this will remove the alpha + // channel (set descriptor==0 if the data has already been + // formatted into RGBA or YA). + void swizzle(uint8_t descriptor, bool squish_alpha); + + // Indicates if the data has an alpha channel. + bool alpha() const; + // Set the alpha channel to the specified value (creates + // alpha channel if it does not exist). + void alpha(const T &value); + + T *ptr(void); + const T *ptr(void) const; + operator T *(); + operator const T *() const; + }; + + // Exception classes... + class exception : std::exception {}; + class invalid : exception {}; + class outofrange : exception {}; + class badtemplate : exception {}; + + // + // These implicitly call read(std::istream *i); to get a + // copy of the header. + // + // If the file's packing or bpp (or whatever...) is sufficiently + // foreign that we can't handle it, we will thow an 'invalid' + // exception. + // + // If the parameter element is out of range for the image (i.e. + // greater than or equal to 'number_of_elements' then an + // exception will be thrown. + // + enum intmode_e { + normal=0, + unformatted=1 + }; + void read(std::istream *io, uint8_t element, fb *buffer, + float64_t scale=0.0); + void read(std::istream *io, uint8_t element, fb *buffer, + float64_t scale=0.0); + void read(std::istream *io, uint8_t element, fb *buffer, + float64_t scale=0.0); + void read(std::istream *io, uint8_t element, fb *buffer, + float64_t scale=0.0, intmode_e mode=normal); + void read(std::istream *io, uint8_t element, fb *buffer, + float64_t scale=0.0, intmode_e mode=normal); + void read(std::istream *io, uint8_t element, fb *buffer, + float64_t scale=0.0, intmode_e mode=normal); + void read(std::istream *io, uint8_t element, fb *buffer, + float64_t scale=0.0, intmode_e mode=normal); + + // + // If not filled out ahead of time (i.e. have 'null' values associated + // with them), then the following fields will be set based on + // the version of the write method called. The defaults chosen are + // affected by the value of the 'compliance' field (described above). + // If compliance is set to 'automatic', then it is silently changed + // on first write to 'dpx1'. + // + // Common across all values of 'compliance': + // + // field default + // ------ ---------------------------------------------------------- + // 17 0 (pixels arranged left to right, top to bottom). + // 19 width of provided framebuffer + // 20 height of provided framebuffer + // 21.9 sizeof()*8 + // 21.1 (see below) + // 21.6 based on depth of framebuffer: + // depth descriptor + // ----- ----------------------------- + // 1 6 (Luminance) + // 2 158 (Luminance Alpha) (proposed) (*) + // 3 50 (RGB) + // 4 51 (RGBA) + // 5 153 (user defined 5 channel image) + // 6 154 (user defined 6 channel image) + // 7 155 (user defined 7 channel image) + // 8 156 (user defined 8 channel image) + // 21.7 1 if bits_per_sample==10, otherwise 2 + // 21.8 set equal to 21.7 (transfer characteristic) + // 21.10 (**)(packing) + // vaheader field valubits_per_sample, packing, + // descriptor, colorimetric_characteristic, transfer_characteristic, + // and offset_to_data will have reasonable default values placed + // in them by the write(...) method. The default values are determined + // on via the following scheme: + // + // + // IMPORTANT NOTE: Unlike the read(...) methods, the write methods + // presume that the interleaved data in the framebuffer is in the + // same order as the descriptor. + // + // All of these fields do not need + // to be filled out prior to calling write(...), , defaults will only be used as needed, colorimetric, and and elements[n].offset_to_data will have + // reasonable defaults set based on the number of channels in the + // framebuffer to write, and the type of the framebuffer. + // + // If there is a reasonable disconnect between the are not specified (i.e. + // are not all 0xff) then appropriate values will be selected + // based on the type provided in the frame buffer. + // If values are provided and do not match the framebuffer type + // then a warning will be posted (see below) and an attempt will + // be made to perform a conversion. If no conversion can be + // performed then an exception is thrown. + // Specifying the elements[n].offset_to_data is particularly + // dangerous as it will will be used without any sort of sanity + // checking and you can easily overwrite critical parts of your + // file. + // + // The number_of_elements value *must* be set prior to the first + // call to write. Failure to do this will cause an exception. + // + // The compliance field (above) must also be set prior to the + // first call/ to write. + // + // Elements should be written (preferably in order), after the + // last element has been written the header should be written. + // + // Like all of the read(...) methods, this will rewind the osream + // to the point it was at when the write(...) method was called. + // + void write(std::ostream *o, uint8_t element, + const fb &buffer, float64_t scale=0.0); + void write(std::ostream *o, uint8_t element, + const fb &buffer, float64_t scale=0.0); + void write(std::ostream *o, uint8_t element, + const fb &buffer, float64_t scale=0.0); + void write(std::ostream *o, uint8_t element, + const fb &buffer, float64_t scale=0.0, + intmode_e mode=normal); + void write(std::ostream *o, uint8_t element, + const fb &buffer, float64_t scale=0.0, + intmode_e mode=normal); + void write(std::ostream *o, uint8_t element, + const fb &buffer, float64_t scale=0.0, + intmode_e mode=normal); + void write(std::ostream *o, uint8_t element, + const fb &buffer, float64_t scale=0.0, + intmode_e mode=normal); + + // Can perform pretty much perform every imaginable conversion + // between two types. While there are a number of functions, they + // all eventually call the same method at the base of things, and + // the variants are to give slightly cleaner interfaces. + // + // The current interface only supports the following types (as either + // inputs and outputs): + // uint8_t (unsigned char) + // uint16_t (unsigned short) + // uint32_t (unsigned int) + // uint64_t (unsigned long long int) + // float16_t (half) + // float32_t (float) + // float64_t (double) + // + // Adding support for signed types is left as an excercise to the + // user. + // + // The parameter meanings are identical across all functions. If + // you are calling a function variant *without* the parameter, it + // defaults to a zero value (the behavior is described below). + // + // O template parameter that is the output type. + // I template parameter that is the input type. + // isb input significant bits, only used when then input type + // is an integer type. Will cause the input to be clipped + // from 0 to (1< + static void convert(O *o, const I *i, uint64_t count); + template + static void convert(O *o, const I *i, float64_t scale, uint64_t count); + template + static void convert(O *o, uint8_t osb, const I *i, uint64_t count); + template + static void convert(O *o, uint8_t osb, const I *i, float64_t scale, + uint64_t count); + template + static void convert(O *o, const I *i, uint8_t isb, uint64_t count); + template + static void convert(O *o, const I *i, uint8_t isb, float64_t scale, + uint64_t count); + template + static void convert(O *o, uint8_t osb, const I *i, uint8_t isb, + uint64_t count); + // This is the actual function that does the work. All of the others + // just fill out default values... + template + static void convert(O *o, uint8_t osb, const I *i, uint8_t isb, + float64_t scale, uint64_t count); + + + // Some static methods to take de-enumerate some of the + // header values. + static std::string smpte_timecode_to_string(uint32_t tc); + static std::string colormetric_to_string(uint8_t id); + static std::string transfer_to_string(uint8_t id); + static std::string video_to_string(uint8_t id); + static std::string encoding_to_string(uint8_t id); + static std::string packing_to_string(uint8_t id); + static std::string bits_per_sample_to_string(uint8_t id); + static std::string orientation_to_string(uint8_t id); + static std::string descriptor_to_string(uint8_t id); }; #include diff --git a/lib/dpx/dpx.tcc b/lib/dpx/dpx.tcc index 8d5b5008..86ea7fb3 100644 --- a/lib/dpx/dpx.tcc +++ b/lib/dpx/dpx.tcc @@ -52,6 +52,12 @@ // THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED. /////////////////////////////////////////////////////////////////////////// +#ifdef WIN32 +#include "math.h" +#define llrint(x) int(x + ((x >= 0.0) ? 0.5 : -0.5)); +#endif + +#include "dpx_exports.hh" template dpx::fb::fb() { @@ -270,7 +276,7 @@ void ctl::dpx::fb::alpha(const T &value) { namespace dpxi { -extern const uint64_t max_int_for_bits[]; +extern DPX_EXPORT const uint64_t max_int_for_bits[]; // // Various functions to perform conversions between different types and diff --git a/lib/dpx/dpx_bits.cc b/lib/dpx/dpx_bits.cc index 9e96e2e8..b08d0c78 100644 --- a/lib/dpx/dpx_bits.cc +++ b/lib/dpx/dpx_bits.cc @@ -122,7 +122,7 @@ const uint64_t max_int_for_bits[]={ 0x0000000000000000ULL, 0x3fffffffffffffffULL, 0x7fffffffffffffffULL, 0xffffffffffffffffULL - }; +}; }; diff --git a/lib/dpx/dpx_bits.hh b/lib/dpx/dpx_bits.hh index 871d9c09..8556783f 100644 --- a/lib/dpx/dpx_bits.hh +++ b/lib/dpx/dpx_bits.hh @@ -58,10 +58,14 @@ #include #include #include + +#include "dpx_exports.hh" + + namespace ctl { namespace dpxi { -extern const uint64_t max_int_for_bits[]; +extern DPX_EXPORT const uint64_t max_int_for_bits[]; } } diff --git a/lib/dpx/dpx_exports.hh b/lib/dpx/dpx_exports.hh new file mode 100644 index 00000000..3316bc62 --- /dev/null +++ b/lib/dpx/dpx_exports.hh @@ -0,0 +1,14 @@ + +#pragma once + +#ifdef _WIN32 + +#ifdef DPX_DLL +# define DPX_EXPORT __declspec(dllimport) +#else +# define DPX_EXPORT __declspec(dllexport) +#endif + +#else +#define DPX_EXPORT +#endif diff --git a/lib/dpx/dpx_rw.cc b/lib/dpx/dpx_rw.cc index 9c7b2d62..c6af716e 100644 --- a/lib/dpx/dpx_rw.cc +++ b/lib/dpx/dpx_rw.cc @@ -56,6 +56,10 @@ #include "dpx_rw.hh" #include +#ifdef WIN32 +#define strncasecmp strnicmp +#endif + namespace ctl { namespace dpxi { diff --git a/lib/dpx/dpx_util.cc b/lib/dpx/dpx_util.cc index 2ee75dba..8e6c738d 100644 --- a/lib/dpx/dpx_util.cc +++ b/lib/dpx/dpx_util.cc @@ -55,7 +55,9 @@ #include "dpx_util.hh" #include #include +#ifndef WIN32 #include +#endif #include namespace ctl {