diff --git a/3rdparty/openexr/AUTHORS.openexr b/3rdparty/openexr/AUTHORS.openexr index 2926b13e83..57299bc391 100644 --- a/3rdparty/openexr/AUTHORS.openexr +++ b/3rdparty/openexr/AUTHORS.openexr @@ -8,6 +8,10 @@ Paul Schneider Bill Anderson Wojciech Jarosz Andrew Kunz +Piotr Stanczyk +Peter Hillman +Nick Porcino +Kimball Thurston Contributors: ------------- @@ -20,6 +24,10 @@ Rodrigo Damazio Greg Ward Joseph Goldstone Loren Carpenter, Pixar Animation Studios +Nicholas Yue +Yunfeng Bai (ILM) +Pascal Jette (Autodesk) +Karl Rasche, DreamWorks Animation Win32 build system: ------------------- diff --git a/3rdparty/openexr/CMakeLists.txt b/3rdparty/openexr/CMakeLists.txt index 88e06e96cf..2ee5146a3d 100644 --- a/3rdparty/openexr/CMakeLists.txt +++ b/3rdparty/openexr/CMakeLists.txt @@ -5,15 +5,75 @@ project(openexr CXX) -if(UNIX) - if(APPLE) - set(HAVE_POSIX_SEMAPHORES 0) # Unnamed semaphores are not supported: https://github.com/opencv/opencv/issues/9361 + +if(NOT HAVE_CXX11) + ocv_check_compiler_flag(CXX "-std=c++11" HAVE_STD_CXX11 "${OpenCV_SOURCE_DIR}/cmake/checks/cxx11.cpp") + if(HAVE_STD_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else() - include(CheckIncludeFile) - check_include_file(semaphore.h HAVE_POSIX_SEMAPHORES) + if(BUILD_OPENEXR) + message(WARNING "OpenCV: builtin OpenEXR requires C++11 support. OpenEXR is disabled.") + endif() + return() endif() endif() + + +set(ILMBASE_VERSION_MAJOR "2") +set(ILMBASE_VERSION_MINOR "3") +set(ILMBASE_VERSION_PATCH "0") + +set(ILMBASE_VERSION "${ILMBASE_VERSION_MAJOR}.${ILMBASE_VERSION_MINOR}.${ILMBASE_VERSION_PATCH}") +set(ILMBASE_VERSION_API ${ILMBASE_VERSION_MAJOR}_${ILMBASE_VERSION_MINOR}) + +set(OPENEXR_VERSION_MAJOR "2") +set(OPENEXR_VERSION_MINOR "3") +set(OPENEXR_VERSION_PATCH "0") + +set(OPENEXR_VERSION "${OPENEXR_VERSION_MAJOR}.${OPENEXR_VERSION_MINOR}.${OPENEXR_VERSION_PATCH}") +set(OPENEXR_VERSION_API ${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}) + +set(OPENEXR_VERSION "${OPENEXR_VERSION}" PARENT_SCOPE) + +if(WIN32) + set(HAVE_COMPLETE_IOMANIP 1) + set(OPENEXR_IMF_HAVE_COMPLETE_IOMANIP 1) + set(PLATFORM_WINDOWS 1) +elseif(APPLE) + set(HAVE_POSIX_SEMAPHORES 0) # Unnamed semaphores are not supported: https://github.com/opencv/opencv/issues/9361 + if(DARWIN) + set(OPENEXR_IMF_HAVE_DARWIN 1) + endif() +elseif(UNIX) + include(CheckIncludeFile) + check_include_file(semaphore.h HAVE_POSIX_SEMAPHORES) +endif() + +set(ILMBASE_VERSION_API "opencv") +set(ILMBASE_INTERNAL_NAMESPACE_CUSTOM 1) +set(IMATH_INTERNAL_NAMESPACE "Imath_${ILMBASE_VERSION_API}") +set(IEX_INTERNAL_NAMESPACE "Iex_${ILMBASE_VERSION_API}") +set(ILMTHREAD_INTERNAL_NAMESPACE "IlmThread_${ILMBASE_VERSION_API}") + +set(ILMBASE_NAMESPACE_CUSTOM 0) +set(IMATH_NAMESPACE "Imath") +set(IEX_NAMESPACE "Iex") +set(ILMTHREAD_NAMESPACE "IlmThread") +set(ILMBASE_VERSION_STRING "\"${ILMBASE_VERSION}\"" ) +set(ILMBASE_PACKAGE_STRING "\"IlmBase ${ILMBASE_VERSION}\"" ) + + +set(OPENEXR_VERSION_API "opencv") +set(OPENEXR_IMF_INTERNAL_NAMESPACE_CUSTOM 1) +set(OPENEXR_IMF_INTERNAL_NAMESPACE "Imf_${ILMBASE_VERSION_API}") +set(OPENEXR_IMF_NAMESPACE_CUSTOM 0) +set(OPENEXR_IMF_NAMESPACE "Imf") + +set(OPENEXR_VERSION_STRING "\"${OPENEXR_VERSION}\"" ) +set(OPENEXR_PACKAGE_STRING "\"OpenEXR ${OPENEXR_VERSION}\"" ) + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/IlmBaseConfig.h.cmakein" "${CMAKE_CURRENT_BINARY_DIR}/IlmBaseConfig.h" @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/OpenEXRConfig.h.cmakein" @@ -23,7 +83,8 @@ set(OPENEXR_INCLUDE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/Half" "${CMAKE_CURRENT_SOURCE_DIR}/Iex" "${CMAKE_CURRENT_SOURCE_DIR}/IlmThread" "${CMAKE_CURRENT_SOURCE_DIR}/Imath" - "${CMAKE_CURRENT_SOURCE_DIR}/IlmImf") + "${CMAKE_CURRENT_SOURCE_DIR}/IlmImf" + "${CMAKE_CURRENT_BINARY_DIR}") ocv_include_directories("${CMAKE_CURRENT_BINARY_DIR}" ${ZLIB_INCLUDE_DIRS} ${OPENEXR_INCLUDE_PATHS}) @@ -31,8 +92,6 @@ file(GLOB lib_srcs Half/half.cpp Iex/*.cpp IlmThread/*.cpp Imath/*.cpp IlmImf/*. file(GLOB lib_hdrs Half/*.h Iex/Iex*.h IlmThread/IlmThread*.h Imath/Imath*.h IlmImf/*.h) list(APPEND lib_hdrs "${CMAKE_CURRENT_BINARY_DIR}/IlmBaseConfig.h" "${CMAKE_CURRENT_BINARY_DIR}/OpenEXRConfig.h") -ocv_list_filterout(lib_srcs IlmImf/b44ExpLogTable.cpp) - if(WIN32) ocv_list_filterout(lib_srcs Posix.*cpp) else() @@ -46,6 +105,10 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow -Wunused -Wsign-compare -Wundef -W -Wdeprecated-declarations -Wmisleading-indentation -Wdeprecated -Wsuggest-override -Winconsistent-missing-override -Wimplicit-fallthrough + -Wtautological-compare # clang + -Wmissing-prototypes # gcc/clang + -Wreorder + -Wunused-result ) if(CV_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0) ocv_warnings_disable(CMAKE_CXX_FLAGS -Wclass-memaccess) @@ -82,7 +145,6 @@ if(NOT BUILD_SHARED_LIBS) ocv_install_target(IlmImf EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) endif() -ocv_install_3rdparty_licenses(openexr LICENSE AUTHORS.ilmbase AUTHORS.openexr fix_msvc2013_errors.patch) +ocv_install_3rdparty_licenses(openexr LICENSE AUTHORS.ilmbase AUTHORS.openexr) set(OPENEXR_INCLUDE_PATHS ${OPENEXR_INCLUDE_PATHS} PARENT_SCOPE) -set(OPENEXR_VERSION "1.7.1" PARENT_SCOPE) diff --git a/3rdparty/openexr/ChangeLog.ilmbase b/3rdparty/openexr/ChangeLog.ilmbase index 2e409d2de4..2e79c0f44f 100644 --- a/3rdparty/openexr/ChangeLog.ilmbase +++ b/3rdparty/openexr/ChangeLog.ilmbase @@ -1,3 +1,30 @@ +Version 2.x.x + * Bumped version to track OpenEXR + (Piotr Stanczyk) + +Version 2.0.1 + * Bumped version to track OpenEXR + (Piotr Stanczyk) + +Version 2.0.0 + * Bumped version to track OpenEXR + (Piotr Stanczyk) + * Numerous minor fixes, missing includes etc + +Version 1.1.0.beta.1 + * Added new module PyIlmBase : python bindings for IlmBase + (Nick Rasmussen) + * Added git specific files + (Piotr Stanczyk) + * Minor fixes for newer gcc versions and OS X. + (misc) + * Preparation for OpenEXR v2 release { remove message for final release } + (Piotr Stanczyk) + * Updated the so verison to 10 + (Piotr Stanczyk) + * Initial use of the CMake build system + (Nicholas Yue) + Version 1.0.3 * Added support for enabling/disabling large stack optimisations, used in halfFunction.h. diff --git a/3rdparty/openexr/ChangeLog.openexr b/3rdparty/openexr/ChangeLog.openexr index 58212f41be..32a2cae774 100644 --- a/3rdparty/openexr/ChangeLog.openexr +++ b/3rdparty/openexr/ChangeLog.openexr @@ -1,5 +1,43 @@ +Version 2.0.1 + * Temporarily turning off optimisation code path + (Piotr Stanczyk) + * Added additional tests for future optimisation refactoring + (Piotr Stanczyk / Peter Hillman) + * Fixes for StringVectors + (Peter Hillman) + * Additional checks for type mismatches + (Peter Hillman) + * Fix for Composite Deep Scanline + (Brendan Bolles) + +Version 2.0.0 + * Updated Documentation + (Peter Hillman) + * Updated Namespacing mechanism + (Piotr Stanczyk) + * Fixes for succd & predd + (Peter Hillman) + * Fixes for FPE control registers + (Piotr Stanczyk) + * Additional checks and tests on DeepImages, scanlines and tiles + (Peter Hillman) + * Folded in Autodesk read optimisations for RGB(A) files + (Pascal Jette, Peter Hillman) + * Updated the bootstrap scripts to use libtoolize if glibtoolize isn't available on darwin. + (Nick Rasmussen) + * Numerous minor fixes, missing includes etc + +Version 2.0.0.beta.1: +* Please read the separate file for v2 additions and changes. + * Added git specific files + (Piotr Stanczyk) + * Updated the so verison to 20 + (Piotr Stanczyk) + * Initial use of the CMake build system + (Nicholas Yue) + Version 1.7.1: - * Updated the .so verison to 7. + * Updated the .so verison to 7. (Piotr Stanczyk) Version 1.7.0: diff --git a/3rdparty/openexr/Half/eLut.h b/3rdparty/openexr/Half/eLut.h index 845bdd038a..f028cdbb70 100644 --- a/3rdparty/openexr/Half/eLut.h +++ b/3rdparty/openexr/Half/eLut.h @@ -4,68 +4,68 @@ // { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1024, 2048, 3072, 4096, 5120, 6144, 7168, - 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, - 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, - 24576, 25600, 26624, 27648, 28672, 29696, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 33792, 34816, 35840, 36864, 37888, 38912, 39936, - 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, - 49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, - 57344, 58368, 59392, 60416, 61440, 62464, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1024, 2048, 3072, 4096, 5120, 6144, 7168, + 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, + 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, + 24576, 25600, 26624, 27648, 28672, 29696, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 33792, 34816, 35840, 36864, 37888, 38912, 39936, + 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, + 49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, + 57344, 58368, 59392, 60416, 61440, 62464, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, }; diff --git a/3rdparty/openexr/Half/half.cpp b/3rdparty/openexr/Half/half.cpp index 281fe5702d..09a50aa2fc 100644 --- a/3rdparty/openexr/Half/half.cpp +++ b/3rdparty/openexr/Half/half.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -53,11 +53,10 @@ using namespace std; // Lookup tables for half-to-float and float-to-half conversion //------------------------------------------------------------- -HALF_EXPORT_CONST half::uif half::_toFloat[1 << 16] = -#include "toFloat.h" -HALF_EXPORT_CONST unsigned short half::_eLut[1 << 9] = -#include "eLut.h" - +HALF_EXPORT const half::uif half::_toFloat[1 << 16] = + #include "toFloat.h" +HALF_EXPORT const unsigned short half::_eLut[1 << 9] = + #include "eLut.h" //----------------------------------------------- // Overflow handler for float-to-half conversion; @@ -65,14 +64,14 @@ HALF_EXPORT_CONST unsigned short half::_eLut[1 << 9] = // which may be trapped by the operating system. //----------------------------------------------- -float +HALF_EXPORT float half::overflow () { volatile float f = 1e10; - for (int i = 0; i < 10; i++) - f *= f; // this will overflow before - // the for­loop terminates + for (int i = 0; i < 10; i++) + f *= f; // this will overflow before + // the for­loop terminates return f; } @@ -82,7 +81,7 @@ half::overflow () // zeroes, denormalized numbers and exponent overflows. //----------------------------------------------------- -short +HALF_EXPORT short half::convert (int i) { // @@ -95,9 +94,9 @@ half::convert (int i) // of float and half (127 versus 15). // - register int s = (i >> 16) & 0x00008000; - register int e = ((i >> 23) & 0x000000ff) - (127 - 15); - register int m = i & 0x007fffff; + int s = (i >> 16) & 0x00008000; + int e = ((i >> 23) & 0x000000ff) - (127 - 15); + int m = i & 0x007fffff; // // Now reassemble s, e and m into a half: @@ -105,115 +104,115 @@ half::convert (int i) if (e <= 0) { - if (e < -10) - { - // - // E is less than -10. The absolute value of f is - // less than HALF_MIN (f may be a small normalized - // float, a denormalized float or a zero). - // - // We convert f to a half zero with the same sign as f. - // - - return s; - } - - // - // E is between -10 and 0. F is a normalized float - // whose magnitude is less than HALF_NRM_MIN. - // - // We convert f to a denormalized half. - // - - // - // Add an explicit leading 1 to the significand. - // - - m = m | 0x00800000; - - // - // Round to m to the nearest (10+e)-bit value (with e between - // -10 and 0); in case of a tie, round to the nearest even value. - // - // Rounding may cause the significand to overflow and make - // our number normalized. Because of the way a half's bits - // are laid out, we don't have to treat this case separately; - // the code below will handle it correctly. - // - - int t = 14 - e; - int a = (1 << (t - 1)) - 1; - int b = (m >> t) & 1; - - m = (m + a + b) >> t; - - // - // Assemble the half from s, e (zero) and m. - // - - return s | m; + if (e < -10) + { + // + // E is less than -10. The absolute value of f is + // less than HALF_MIN (f may be a small normalized + // float, a denormalized float or a zero). + // + // We convert f to a half zero with the same sign as f. + // + + return s; + } + + // + // E is between -10 and 0. F is a normalized float + // whose magnitude is less than HALF_NRM_MIN. + // + // We convert f to a denormalized half. + // + + // + // Add an explicit leading 1 to the significand. + // + + m = m | 0x00800000; + + // + // Round to m to the nearest (10+e)-bit value (with e between + // -10 and 0); in case of a tie, round to the nearest even value. + // + // Rounding may cause the significand to overflow and make + // our number normalized. Because of the way a half's bits + // are laid out, we don't have to treat this case separately; + // the code below will handle it correctly. + // + + int t = 14 - e; + int a = (1 << (t - 1)) - 1; + int b = (m >> t) & 1; + + m = (m + a + b) >> t; + + // + // Assemble the half from s, e (zero) and m. + // + + return s | m; } else if (e == 0xff - (127 - 15)) { - if (m == 0) - { - // - // F is an infinity; convert f to a half - // infinity with the same sign as f. - // - - return s | 0x7c00; - } - else - { - // - // F is a NAN; we produce a half NAN that preserves - // the sign bit and the 10 leftmost bits of the - // significand of f, with one exception: If the 10 - // leftmost bits are all zero, the NAN would turn - // into an infinity, so we have to set at least one - // bit in the significand. - // - - m >>= 13; - return s | 0x7c00 | m | (m == 0); - } + if (m == 0) + { + // + // F is an infinity; convert f to a half + // infinity with the same sign as f. + // + + return s | 0x7c00; + } + else + { + // + // F is a NAN; we produce a half NAN that preserves + // the sign bit and the 10 leftmost bits of the + // significand of f, with one exception: If the 10 + // leftmost bits are all zero, the NAN would turn + // into an infinity, so we have to set at least one + // bit in the significand. + // + + m >>= 13; + return s | 0x7c00 | m | (m == 0); + } } else { - // - // E is greater than zero. F is a normalized float. - // We try to convert f to a normalized half. - // - - // - // Round to m to the nearest 10-bit value. In case of - // a tie, round to the nearest even value. - // - - m = m + 0x00000fff + ((m >> 13) & 1); - - if (m & 0x00800000) - { - m = 0; // overflow in significand, - e += 1; // adjust exponent - } - - // - // Handle exponent overflow - // - - if (e > 30) - { - overflow (); // Cause a hardware floating point overflow; - return s | 0x7c00; // if this returns, the half becomes an - } // infinity with the same sign as f. - - // - // Assemble the half from s, e and m. - // - - return s | (e << 10) | (m >> 13); + // + // E is greater than zero. F is a normalized float. + // We try to convert f to a normalized half. + // + + // + // Round to m to the nearest 10-bit value. In case of + // a tie, round to the nearest even value. + // + + m = m + 0x00000fff + ((m >> 13) & 1); + + if (m & 0x00800000) + { + m = 0; // overflow in significand, + e += 1; // adjust exponent + } + + // + // Handle exponent overflow + // + + if (e > 30) + { + overflow (); // Cause a hardware floating point overflow; + return s | 0x7c00; // if this returns, the half becomes an + } // infinity with the same sign as f. + + // + // Assemble the half from s, e and m. + // + + return s | (e << 10) | (m >> 13); } } @@ -222,7 +221,7 @@ half::convert (int i) // Stream I/O operators //--------------------- -ostream & +HALF_EXPORT ostream & operator << (ostream &os, half h) { os << float (h); @@ -230,7 +229,7 @@ operator << (ostream &os, half h) } -istream & +HALF_EXPORT istream & operator >> (istream &is, half &h) { float f; @@ -245,22 +244,22 @@ operator >> (istream &is, half &h) // floats and halfs, mostly for debugging //--------------------------------------- -void +HALF_EXPORT void printBits (ostream &os, half h) { unsigned short b = h.bits(); for (int i = 15; i >= 0; i--) { - os << (((b >> i) & 1)? '1': '0'); + os << (((b >> i) & 1)? '1': '0'); - if (i == 15 || i == 10) - os << ' '; + if (i == 15 || i == 10) + os << ' '; } } -void +HALF_EXPORT void printBits (ostream &os, float f) { half::uif x; @@ -268,32 +267,32 @@ printBits (ostream &os, float f) for (int i = 31; i >= 0; i--) { - os << (((x.i >> i) & 1)? '1': '0'); + os << (((x.i >> i) & 1)? '1': '0'); - if (i == 31 || i == 23) - os << ' '; + if (i == 31 || i == 23) + os << ' '; } } -void +HALF_EXPORT void printBits (char c[19], half h) { unsigned short b = h.bits(); for (int i = 15, j = 0; i >= 0; i--, j++) { - c[j] = (((b >> i) & 1)? '1': '0'); + c[j] = (((b >> i) & 1)? '1': '0'); - if (i == 15 || i == 10) - c[++j] = ' '; + if (i == 15 || i == 10) + c[++j] = ' '; } - + c[18] = 0; } -void +HALF_EXPORT void printBits (char c[35], float f) { half::uif x; @@ -301,10 +300,10 @@ printBits (char c[35], float f) for (int i = 31, j = 0; i >= 0; i--, j++) { - c[j] = (((x.i >> i) & 1)? '1': '0'); + c[j] = (((x.i >> i) & 1)? '1': '0'); - if (i == 31 || i == 23) - c[++j] = ' '; + if (i == 31 || i == 23) + c[++j] = ' '; } c[34] = 0; diff --git a/3rdparty/openexr/Half/half.h b/3rdparty/openexr/Half/half.h index da5500e48b..fe8c0a149b 100644 --- a/3rdparty/openexr/Half/half.h +++ b/3rdparty/openexr/Half/half.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -85,21 +85,10 @@ #ifndef _HALF_H_ #define _HALF_H_ +#include "halfExport.h" // for definition of HALF_EXPORT #include -#if defined(OPENEXR_DLL) - #if defined(HALF_EXPORTS) - #define HALF_EXPORT __declspec(dllexport) - #else - #define HALF_EXPORT __declspec(dllimport) - #endif - #define HALF_EXPORT_CONST -#else - #define HALF_EXPORT - #define HALF_EXPORT_CONST const -#endif - -class HALF_EXPORT half +class half { public: @@ -208,45 +197,47 @@ class HALF_EXPORT half // Access to the internal representation //-------------------------------------- - unsigned short bits () const; - void setBits (unsigned short bits); + HALF_EXPORT unsigned short bits () const; + HALF_EXPORT void setBits (unsigned short bits); public: union uif { - unsigned int i; - float f; + unsigned int i; + float f; }; private: - static short convert (int i); - static float overflow (); + HALF_EXPORT static short convert (int i); + HALF_EXPORT static float overflow (); - unsigned short _h; + unsigned short _h; - static HALF_EXPORT_CONST uif _toFloat[1 << 16]; - static HALF_EXPORT_CONST unsigned short _eLut[1 << 9]; + HALF_EXPORT static const uif _toFloat[1 << 16]; + HALF_EXPORT static const unsigned short _eLut[1 << 9]; }; + + //----------- // Stream I/O //----------- -HALF_EXPORT std::ostream & operator << (std::ostream &os, half h); -HALF_EXPORT std::istream & operator >> (std::istream &is, half &h); +HALF_EXPORT std::ostream & operator << (std::ostream &os, half h); +HALF_EXPORT std::istream & operator >> (std::istream &is, half &h); //---------- // Debugging //---------- -HALF_EXPORT void printBits (std::ostream &os, half h); -HALF_EXPORT void printBits (std::ostream &os, float f); -HALF_EXPORT void printBits (char c[19], half h); -HALF_EXPORT void printBits (char c[35], float f); +HALF_EXPORT void printBits (std::ostream &os, half h); +HALF_EXPORT void printBits (std::ostream &os, float f); +HALF_EXPORT void printBits (char c[19], half h); +HALF_EXPORT void printBits (char c[35], float f); //------------------------------------------------------------------------- @@ -266,7 +257,7 @@ HALF_EXPORT void printBits (char c[35], float f); #define HALF_MAX 65504.0f // Largest positive half #define HALF_EPSILON 0.00097656f // Smallest positive e for which - // half (1.0 + e) != half (1.0) + // half (1.0 + e) != half (1.0) #else #define HALF_MIN 5.96046448e-08 // Smallest positive half @@ -276,35 +267,39 @@ HALF_EXPORT void printBits (char c[35], float f); #define HALF_MAX 65504.0 // Largest positive half #define HALF_EPSILON 0.00097656 // Smallest positive e for which - // half (1.0 + e) != half (1.0) + // half (1.0 + e) != half (1.0) #endif #define HALF_MANT_DIG 11 // Number of digits in mantissa - // (significand + hidden leading 1) + // (significand + hidden leading 1) #define HALF_DIG 2 // Number of base 10 digits that - // can be represented without change + // can be represented without change + +#define HALF_DECIMAL_DIG 5 // Number of base-10 digits that are + // necessary to uniquely represent all + // distinct values #define HALF_RADIX 2 // Base of the exponent #define HALF_MIN_EXP -13 // Minimum negative integer such that - // HALF_RADIX raised to the power of - // one less than that integer is a - // normalized half + // HALF_RADIX raised to the power of + // one less than that integer is a + // normalized half #define HALF_MAX_EXP 16 // Maximum positive integer such that - // HALF_RADIX raised to the power of - // one less than that integer is a - // normalized half + // HALF_RADIX raised to the power of + // one less than that integer is a + // normalized half #define HALF_MIN_10_EXP -4 // Minimum positive integer such - // that 10 raised to that power is - // a normalized half + // that 10 raised to that power is + // a normalized half #define HALF_MAX_10_EXP 4 // Maximum positive integer such - // that 10 raised to that power is - // a normalized half + // that 10 raised to that power is + // a normalized half //--------------------------------------------------------------------------- @@ -317,9 +312,9 @@ HALF_EXPORT void printBits (char c[35], float f); // floating point number, whose bits are arranged as follows: // // 31 (msb) -// | +// | // | 30 23 -// | | | +// | | | // | | | 22 0 (lsb) // | | | | | // X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX @@ -363,7 +358,7 @@ HALF_EXPORT void printBits (char c[35], float f); // Here is the bit-layout for a half number, h: // // 15 (msb) -// | +// | // | 14 10 // | | | // | | | 9 0 (lsb) @@ -443,53 +438,53 @@ half::half (float f) if (f == 0) { - // - // Common special case - zero. - // Preserve the zero's sign bit. - // + // + // Common special case - zero. + // Preserve the zero's sign bit. + // - _h = (x.i >> 16); + _h = (x.i >> 16); } else { - // - // We extract the combined sign and exponent, e, from our - // floating-point number, f. Then we convert e to the sign - // and exponent of the half number via a table lookup. - // - // For the most common case, where a normalized half is produced, - // the table lookup returns a non-zero value; in this case, all - // we have to do is round f's significand to 10 bits and combine - // the result with e. - // - // For all other cases (overflow, zeroes, denormalized numbers - // resulting from underflow, infinities and NANs), the table - // lookup returns zero, and we call a longer, non-inline function - // to do the float-to-half conversion. - // - - register int e = (x.i >> 23) & 0x000001ff; - - e = _eLut[e]; - - if (e) - { - // - // Simple case - round the significand, m, to 10 - // bits and combine it with the sign and exponent. - // - - register int m = x.i & 0x007fffff; - _h = e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13); - } - else - { - // - // Difficult case - call a function. - // - - _h = convert (x.i); - } + // + // We extract the combined sign and exponent, e, from our + // floating-point number, f. Then we convert e to the sign + // and exponent of the half number via a table lookup. + // + // For the most common case, where a normalized half is produced, + // the table lookup returns a non-zero value; in this case, all + // we have to do is round f's significand to 10 bits and combine + // the result with e. + // + // For all other cases (overflow, zeroes, denormalized numbers + // resulting from underflow, infinities and NANs), the table + // lookup returns zero, and we call a longer, non-inline function + // to do the float-to-half conversion. + // + + int e = (x.i >> 23) & 0x000001ff; + + e = _eLut[e]; + + if (e) + { + // + // Simple case - round the significand, m, to 10 + // bits and combine it with the sign and exponent. + // + + int m = x.i & 0x007fffff; + _h = (unsigned short)(e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13)); + } + else + { + // + // Difficult case - call a function. + // + + _h = convert (x.i); + } } } @@ -517,7 +512,7 @@ half::round (unsigned int n) const // if (n >= 10) - return *this; + return *this; // // Disassemble h into the sign, s, @@ -544,13 +539,13 @@ half::round (unsigned int n) const if (e >= 0x7c00) { - // - // Overflow occurred -- truncate instead of rounding. - // + // + // Overflow occurred -- truncate instead of rounding. + // - e = _h; - e >>= 10 - n; - e <<= 10 - n; + e = _h; + e >>= 10 - n; + e <<= 10 - n; } // @@ -568,7 +563,7 @@ half::round (unsigned int n) const // Other inline functions //----------------------- -inline half +inline half half::operator - () const { half h; @@ -657,7 +652,7 @@ half::operator /= (float f) } -inline bool +inline bool half::isFinite () const { unsigned short e = (_h >> 10) & 0x001f; @@ -707,7 +702,7 @@ half::isInfinity () const } -inline bool +inline bool half::isNegative () const { return (_h & 0x8000) != 0; diff --git a/3rdparty/openexr/Imath/ImathGLU.h b/3rdparty/openexr/Half/halfExport.h similarity index 80% rename from 3rdparty/openexr/Imath/ImathGLU.h rename to 3rdparty/openexr/Half/halfExport.h index 1c01697f9d..6ae84e78e7 100644 --- a/3rdparty/openexr/Imath/ImathGLU.h +++ b/3rdparty/openexr/Half/halfExport.h @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2008, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC // // All rights reserved. @@ -32,23 +32,20 @@ // /////////////////////////////////////////////////////////////////////////// +#ifndef HALFEXPORT_H +#define HALFEXPORT_H +#if defined(OPENEXR_DLL) + #if defined(HALF_EXPORTS) + #define HALF_EXPORT __declspec(dllexport) + #else + #define HALF_EXPORT __declspec(dllimport) + #endif + #define HALF_EXPORT_CONST +#else + #define HALF_EXPORT + #define HALF_EXPORT_CONST const +#endif -#ifndef INCLUDED_IMATHGLU_H -#define INCLUDED_IMATHGLU_H - -#include -#include - -#include "ImathVec.h" - -inline -void -gluLookAt(const Imath::V3f &pos, const Imath::V3f &interest, const Imath::V3f &up) -{ - gluLookAt(pos.x, pos.y, pos.z, - interest.x, interest.y, interest.z, - up.x, up.y, up.z); -} +#endif // #ifndef HALFEXPORT_H -#endif diff --git a/3rdparty/openexr/Half/halfFunction.h b/3rdparty/openexr/Half/halfFunction.h index 6e0b990da1..98c1d17bd3 100644 --- a/3rdparty/openexr/Half/halfFunction.h +++ b/3rdparty/openexr/Half/halfFunction.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -85,10 +85,10 @@ #include "half.h" -#include -#ifndef ILMBASE_HAVE_LARGE_STACK +#include "IlmBaseConfig.h" +#ifndef ILMBASE_HAVE_LARGE_STACK #include // need this for memset -#else +#else #endif #include @@ -105,17 +105,17 @@ class halfFunction template halfFunction (Function f, - half domainMin = -HALF_MAX, - half domainMax = HALF_MAX, - T defaultValue = 0, - T posInfValue = 0, - T negInfValue = 0, - T nanValue = 0); + half domainMin = -HALF_MAX, + half domainMax = HALF_MAX, + T defaultValue = 0, + T posInfValue = 0, + T negInfValue = 0, + T nanValue = 0); #ifndef ILMBASE_HAVE_LARGE_STACK - ~halfFunction () { delete [] _lut; } + ~halfFunction () { delete [] _lut; } #endif - + //----------- // Evaluation //----------- @@ -123,6 +123,7 @@ class halfFunction T operator () (half x) const; private: + #ifdef ILMBASE_HAVE_LARGE_STACK T _lut[1 << 16]; #else @@ -138,31 +139,31 @@ class halfFunction template template halfFunction::halfFunction (Function f, - half domainMin, - half domainMax, - T defaultValue, - T posInfValue, - T negInfValue, - T nanValue) + half domainMin, + half domainMax, + T defaultValue, + T posInfValue, + T negInfValue, + T nanValue) { #ifndef ILMBASE_HAVE_LARGE_STACK _lut = new T[1<<16]; memset (_lut, 0 , (1<<16) * sizeof(T)); #endif - + for (int i = 0; i < (1 << 16); i++) { - half x; - x.setBits (i); - - if (x.isNan()) - _lut[i] = nanValue; - else if (x.isInfinity()) - _lut[i] = x.isNegative()? negInfValue: posInfValue; - else if (x < domainMin || x > domainMax) - _lut[i] = defaultValue; - else - _lut[i] = f (x); + half x; + x.setBits (i); + + if (x.isNan()) + _lut[i] = nanValue; + else if (x.isInfinity()) + _lut[i] = x.isNegative()? negInfValue: posInfValue; + else if (x < domainMin || x > domainMax) + _lut[i] = defaultValue; + else + _lut[i] = f (x); } } diff --git a/3rdparty/openexr/Half/halfLimits.h b/3rdparty/openexr/Half/halfLimits.h index 77dafff508..351db8f7a0 100644 --- a/3rdparty/openexr/Half/halfLimits.h +++ b/3rdparty/openexr/Half/halfLimits.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -94,6 +94,15 @@ class numeric_limits static const bool traps = true; static const bool tinyness_before = false; static const float_round_style round_style = round_to_nearest; + +#if __cplusplus >= 201103L + + // C++11 additions. + static constexpr int max_digits10 = HALF_DECIMAL_DIG; + static half lowest () {return -HALF_MAX;} + +#endif + }; diff --git a/3rdparty/openexr/Half/toFloat.cpp b/3rdparty/openexr/Half/toFloat.cpp deleted file mode 100644 index 1327f56b47..0000000000 --- a/3rdparty/openexr/Half/toFloat.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas -// Digital Ltd. LLC -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Industrial Light & Magic nor the names of -// its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////// - - - - -//--------------------------------------------------------------------------- -// -// toFloat -// -// A program to generate the lookup table for half-to-float -// conversion needed by class half. -// The program loops over all 65536 possible half numbers, -// converts each of them to a float, and prints the result. -// -//--------------------------------------------------------------------------- - - -#include -#include - -using namespace std; - -//--------------------------------------------------- -// Interpret an unsigned short bit pattern as a half, -// and convert that half to the corresponding float's -// bit pattern. -//--------------------------------------------------- - -unsigned int -halfToFloat (unsigned short y) -{ - - int s = (y >> 15) & 0x00000001; - int e = (y >> 10) & 0x0000001f; - int m = y & 0x000003ff; - - if (e == 0) - { - if (m == 0) - { - // - // Plus or minus zero - // - - return s << 31; - } - else - { - // - // Denormalized number -- renormalize it - // - - while (!(m & 0x00000400)) - { - m <<= 1; - e -= 1; - } - - e += 1; - m &= ~0x00000400; - } - } - else if (e == 31) - { - if (m == 0) - { - // - // Positive or negative infinity - // - - return (s << 31) | 0x7f800000; - } - else - { - // - // Nan -- preserve sign and significand bits - // - - return (s << 31) | 0x7f800000 | (m << 13); - } - } - - // - // Normalized number - // - - e = e + (127 - 15); - m = m << 13; - - // - // Assemble s, e and m. - // - - return (s << 31) | (e << 23) | m; -} - - -//--------------------------------------------- -// Main - prints the half-to-float lookup table -//--------------------------------------------- - -int -main () -{ - cout.precision (9); - cout.setf (ios_base::hex, ios_base::basefield); - - cout << "//\n" - "// This is an automatically generated file.\n" - "// Do not edit.\n" - "//\n\n"; - - cout << "{\n "; - - const int iMax = (1 << 16); - - for (int i = 0; i < iMax; i++) - { - cout << "{0x" << setfill ('0') << setw (8) << halfToFloat (i) << "}, "; - - if (i % 4 == 3) - { - cout << "\n"; - - if (i < iMax - 1) - cout << " "; - } - } - - cout << "};\n"; - return 0; -} diff --git a/3rdparty/openexr/Iex/Iex.h b/3rdparty/openexr/Iex/Iex.h index 9f68576b9f..a0fd31d017 100644 --- a/3rdparty/openexr/Iex/Iex.h +++ b/3rdparty/openexr/Iex/Iex.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR diff --git a/3rdparty/openexr/Iex/IexBaseExc.cpp b/3rdparty/openexr/Iex/IexBaseExc.cpp index eb0a1e4e76..cd975c3d10 100644 --- a/3rdparty/openexr/Iex/IexBaseExc.cpp +++ b/3rdparty/openexr/Iex/IexBaseExc.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -40,19 +40,27 @@ // //--------------------------------------------------------------------- +#include "IexExport.h" #include "IexBaseExc.h" +#include "IexMacros.h" -namespace Iex { -namespace { +#ifdef PLATFORM_WINDOWS +#include +#endif +#include + +IEX_INTERNAL_NAMESPACE_SOURCE_ENTER -StackTracer currentStackTracer = 0; +namespace { + +StackTracer currentStackTracer = 0; } // namespace -void +void setStackTracer (StackTracer stackTracer) { currentStackTracer = stackTracer; @@ -67,7 +75,7 @@ stackTracer () BaseExc::BaseExc (const char* s) throw () : - std::string (s? s: ""), + _message (s? s: ""), _stackTrace (currentStackTracer? currentStackTracer(): "") { // empty @@ -75,7 +83,7 @@ BaseExc::BaseExc (const char* s) throw () : BaseExc::BaseExc (const std::string &s) throw () : - std::string (s), + _message (s), _stackTrace (currentStackTracer? currentStackTracer(): "") { // empty @@ -83,7 +91,7 @@ BaseExc::BaseExc (const std::string &s) throw () : BaseExc::BaseExc (std::stringstream &s) throw () : - std::string (s.str()), + _message (s.str()), _stackTrace (currentStackTracer? currentStackTracer(): "") { // empty @@ -91,7 +99,7 @@ BaseExc::BaseExc (std::stringstream &s) throw () : BaseExc::BaseExc (const BaseExc &be) throw () : - std::string (be), + _message (be._message), _stackTrace (be._stackTrace) { // empty @@ -107,23 +115,99 @@ BaseExc::~BaseExc () throw () const char * BaseExc::what () const throw () { - return c_str(); + return _message.c_str(); } BaseExc & BaseExc::assign (std::stringstream &s) { - std::string::assign (s.str()); + _message.assign (s.str()); return *this; } BaseExc & BaseExc::append (std::stringstream &s) { - std::string::append (s.str()); + _message.append (s.str()); return *this; } +const std::string & +BaseExc::message() const +{ + return _message; +} -} // namespace Iex +BaseExc & +BaseExc::operator = (std::stringstream &s) +{ + return assign (s); +} + + +BaseExc & +BaseExc::operator += (std::stringstream &s) +{ + return append (s); +} + + +BaseExc & +BaseExc::assign (const char *s) +{ + _message.assign(s); + return *this; +} + + +BaseExc & +BaseExc::operator = (const char *s) +{ + return assign(s); +} + + +BaseExc & +BaseExc::append (const char *s) +{ + _message.append(s); + return *this; +} + + +BaseExc & +BaseExc::operator += (const char *s) +{ + return append(s); +} + + +const std::string & +BaseExc::stackTrace () const +{ + return _stackTrace; +} + + +IEX_INTERNAL_NAMESPACE_SOURCE_EXIT + + +#ifdef PLATFORM_WINDOWS + +#pragma optimize("", off) +void +iex_debugTrap() +{ + if (0 != getenv("IEXDEBUGTHROW")) + ::DebugBreak(); +} +#else +void +iex_debugTrap() +{ + // how to in Linux? + if (0 != ::getenv("IEXDEBUGTHROW")) + __builtin_trap(); +} +#endif diff --git a/3rdparty/openexr/Iex/IexBaseExc.h b/3rdparty/openexr/Iex/IexBaseExc.h index 0956e3b4e1..30cb17f509 100644 --- a/3rdparty/openexr/Iex/IexBaseExc.h +++ b/3rdparty/openexr/Iex/IexBaseExc.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,10 +33,11 @@ /////////////////////////////////////////////////////////////////////////// - #ifndef INCLUDED_IEXBASEEXC_H #define INCLUDED_IEXBASEEXC_H +#include "IexNamespace.h" +#include "IexExport.h" //---------------------------------------------------------- // @@ -49,18 +50,14 @@ #include #include -namespace Iex { +IEX_INTERNAL_NAMESPACE_HEADER_ENTER -#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER -// Tell MS VC++ to suppress exception specification warnings -#pragma warning(disable:4290) -#endif //------------------------------- // Our most basic exception class //------------------------------- -class BaseExc: public std::string, public std::exception +class BaseExc: public std::exception { public: @@ -68,29 +65,29 @@ class BaseExc: public std::string, public std::exception // Constructors and destructor //---------------------------- - BaseExc (const char *s = 0) throw(); // std::string (s) - BaseExc (const std::string &s) throw(); // std::string (s) - BaseExc (std::stringstream &s) throw(); // std::string (s.str()) + IEX_EXPORT BaseExc (const char *s = 0) throw(); // std::string (s) + IEX_EXPORT BaseExc (const std::string &s) throw(); // std::string (s) + IEX_EXPORT BaseExc (std::stringstream &s) throw(); // std::string (s.str()) - BaseExc (const BaseExc &be) throw(); - virtual ~BaseExc () throw (); + IEX_EXPORT BaseExc (const BaseExc &be) throw(); + IEX_EXPORT virtual ~BaseExc () throw (); - //-------------------------------------------- - // what() method -- e.what() returns e.c_str() - //-------------------------------------------- + //--------------------------------------------------- + // what() method -- e.what() returns _message.c_str() + //--------------------------------------------------- - virtual const char * what () const throw (); + IEX_EXPORT virtual const char * what () const throw (); //-------------------------------------------------- // Convenient methods to change the exception's text //-------------------------------------------------- - BaseExc & assign (std::stringstream &s); // assign (s.str()) - BaseExc & operator = (std::stringstream &s); + IEX_EXPORT BaseExc & assign (std::stringstream &s); // assign (s.str()) + IEX_EXPORT BaseExc & operator = (std::stringstream &s); - BaseExc & append (std::stringstream &s); // append (s.str()) - BaseExc & operator += (std::stringstream &s); + IEX_EXPORT BaseExc & append (std::stringstream &s); // append (s.str()) + IEX_EXPORT BaseExc & operator += (std::stringstream &s); //-------------------------------------------------- @@ -98,12 +95,17 @@ class BaseExc: public std::string, public std::exception // the definitions above. //-------------------------------------------------- - BaseExc & assign (const char *s); - BaseExc & operator = (const char *s); + IEX_EXPORT BaseExc & assign (const char *s); + IEX_EXPORT BaseExc & operator = (const char *s); - BaseExc & append (const char *s); - BaseExc & operator += (const char *s); + IEX_EXPORT BaseExc & append (const char *s); + IEX_EXPORT BaseExc & operator += (const char *s); + //--------------------------------------------------- + // Access to the string representation of the message + //--------------------------------------------------- + + IEX_EXPORT const std::string & message () const; //-------------------------------------------------- // Stack trace for the point at which the exception @@ -112,11 +114,12 @@ class BaseExc: public std::string, public std::exception // has been installed (see below, setStackTracer()). //-------------------------------------------------- - const std::string & stackTrace () const; + IEX_EXPORT const std::string & stackTrace () const; private: - std::string _stackTrace; + std::string _message; + std::string _stackTrace; }; @@ -125,55 +128,59 @@ class BaseExc: public std::string, public std::exception // class derived directly or indirectly from BaseExc: //----------------------------------------------------- -#define DEFINE_EXC(name, base) \ - class name: public base \ - { \ - public: \ - name (const char* text=0) throw(): base (text) {} \ - name (const std::string &text) throw(): base (text) {} \ - name (std::stringstream &text) throw(): base (text) {} \ +#define DEFINE_EXC_EXP(exp, name, base) \ + class name: public base \ + { \ + public: \ + exp name() throw(): base (0) {} \ + exp name (const char* text) throw(): base (text) {} \ + exp name (const std::string &text) throw(): base (text) {} \ + exp name (std::stringstream &text) throw(): base (text) {} \ + exp ~name() throw() { } \ }; +// For backward compatibility. +#define DEFINE_EXC(name, base) DEFINE_EXC_EXP(, name, base) + //-------------------------------------------------------- // Some exceptions which should be useful in most programs //-------------------------------------------------------- +DEFINE_EXC_EXP (IEX_EXPORT, ArgExc, BaseExc) // Invalid arguments to a function call -DEFINE_EXC (ArgExc, BaseExc) // Invalid arguments to a function call +DEFINE_EXC_EXP (IEX_EXPORT, LogicExc, BaseExc) // General error in a program's logic, + // for example, a function was called + // in a context where the call does + // not make sense. -DEFINE_EXC (LogicExc, BaseExc) // General error in a program's logic, - // for example, a function was called - // in a context where the call does - // not make sense. +DEFINE_EXC_EXP (IEX_EXPORT, InputExc, BaseExc) // Invalid input data, e.g. from a file -DEFINE_EXC (InputExc, BaseExc) // Invalid input data, e.g. from a file +DEFINE_EXC_EXP (IEX_EXPORT, IoExc, BaseExc) // Input or output operation failed -DEFINE_EXC (IoExc, BaseExc) // Input or output operation failed +DEFINE_EXC_EXP (IEX_EXPORT, MathExc, BaseExc) // Arithmetic exception; more specific + // exceptions derived from this class + // are defined in ExcMath.h -DEFINE_EXC (MathExc, BaseExc) // Arithmetic exception; more specific - // exceptions derived from this class - // are defined in ExcMath.h +DEFINE_EXC_EXP (IEX_EXPORT, ErrnoExc, BaseExc) // Base class for exceptions corresponding + // to errno values (see errno.h); more + // specific exceptions derived from this + // class are defined in ExcErrno.h -DEFINE_EXC (ErrnoExc, BaseExc) // Base class for exceptions corresponding - // to errno values (see errno.h); more - // specific exceptions derived from this - // class are defined in ExcErrno.h +DEFINE_EXC_EXP (IEX_EXPORT, NoImplExc, BaseExc) // Missing method exception e.g. from a + // call to a method that is only partially + // or not at all implemented. A reminder + // to lazy software people to get back + // to work. -DEFINE_EXC (NoImplExc, BaseExc) // Missing method exception e.g. from a - // call to a method that is only partially - // or not at all implemented. A reminder - // to lazy software people to get back - // to work. +DEFINE_EXC_EXP (IEX_EXPORT, NullExc, BaseExc) // A pointer is inappropriately null. -DEFINE_EXC (NullExc, BaseExc) // A pointer is inappropriately null. - -DEFINE_EXC (TypeExc, BaseExc) // An object is an inappropriate type, - // i.e. a dynamnic_cast failed. +DEFINE_EXC_EXP (IEX_EXPORT, TypeExc, BaseExc) // An object is an inappropriate type, + // i.e. a dynamnic_cast failed. //---------------------------------------------------------------------- // Stack-tracing support: -// +// // setStackTracer(st) // // installs a stack-tracing routine, st, which will be called from @@ -194,73 +201,15 @@ DEFINE_EXC (TypeExc, BaseExc) // An object is an inappropriate type, // // returns a pointer to the current stack-tracing routine, or 0 // if there is no current stack stack-tracing routine. -// +// //---------------------------------------------------------------------- typedef std::string (* StackTracer) (); -void setStackTracer (StackTracer stackTracer); -StackTracer stackTracer (); - - -//----------------- -// Inline functions -//----------------- - -inline BaseExc & -BaseExc::operator = (std::stringstream &s) -{ - return assign (s); -} - - -inline BaseExc & -BaseExc::operator += (std::stringstream &s) -{ - return append (s); -} - - -inline BaseExc & -BaseExc::assign (const char *s) -{ - std::string::assign(s); - return *this; -} - - -inline BaseExc & -BaseExc::operator = (const char *s) -{ - return assign(s); -} - - -inline BaseExc & -BaseExc::append (const char *s) -{ - std::string::append(s); - return *this; -} - - -inline BaseExc & -BaseExc::operator += (const char *s) -{ - return append(s); -} - - -inline const std::string & -BaseExc::stackTrace () const -{ - return _stackTrace; -} +IEX_EXPORT void setStackTracer (StackTracer stackTracer); +IEX_EXPORT StackTracer stackTracer (); -#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER -#pragma warning(default:4290) -#endif -} // namespace Iex +IEX_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IEXBASEEXC_H diff --git a/3rdparty/openexr/Iex/IexErrnoExc.h b/3rdparty/openexr/Iex/IexErrnoExc.h index 7f2ac75102..027c7a4e9c 100644 --- a/3rdparty/openexr/Iex/IexErrnoExc.h +++ b/3rdparty/openexr/Iex/IexErrnoExc.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,8 +45,7 @@ #include "IexBaseExc.h" -namespace Iex { - +IEX_INTERNAL_NAMESPACE_HEADER_ENTER DEFINE_EXC (EpermExc, ErrnoExc) DEFINE_EXC (EnoentExc, ErrnoExc) @@ -204,7 +203,6 @@ DEFINE_EXC (EcantextentExc, ErrnoExc) DEFINE_EXC (EinvaltimeExc, ErrnoExc) DEFINE_EXC (EdestroyedExc, ErrnoExc) - -} // namespace Iex +IEX_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/Iex/IexExport.h b/3rdparty/openexr/Iex/IexExport.h new file mode 100644 index 0000000000..270c1cf49d --- /dev/null +++ b/3rdparty/openexr/Iex/IexExport.h @@ -0,0 +1,51 @@ +#ifndef IEXEXPORT_H +#define IEXEXPORT_H + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#if defined(OPENEXR_DLL) + #if defined(IEX_EXPORTS) + #define IEX_EXPORT __declspec(dllexport) + #else + #define IEX_EXPORT __declspec(dllimport) + #endif + #define IEX_EXPORT_CONST +#else + #define IEX_EXPORT + #define IEX_EXPORT_CONST const +#endif + +#endif // #ifndef IEXEXPORT_H + diff --git a/3rdparty/openexr/Iex/IexForward.h b/3rdparty/openexr/Iex/IexForward.h new file mode 100644 index 0000000000..743771cbb1 --- /dev/null +++ b/3rdparty/openexr/Iex/IexForward.h @@ -0,0 +1,229 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IEXFORWARD_H +#define INCLUDED_IEXFORWARD_H + +#include "IexNamespace.h" + +IEX_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Base exceptions. +// + +class BaseExc; +class ArgExc; +class LogicExc; +class InputExc; +class IoExc; +class MathExc; +class ErrnoExc; +class NoImplExc; +class NullExc; +class TypeExc; + +// +// Math exceptions. +// + +class OverflowExc; +class UnderflowExc; +class DivzeroExc; +class InexactExc; +class InvalidFpOpExc; + +// +// Errno exceptions. +// + +class EpermExc; +class EnoentExc; +class EsrchExc; +class EintrExc; +class EioExc; +class EnxioExc; +class E2bigExc; +class EnoexecExc; +class EbadfExc; +class EchildExc; +class EagainExc; +class EnomemExc; +class EaccesExc; +class EfaultExc; +class EnotblkExc; +class EbusyExc; +class EexistExc; +class ExdevExc; +class EnodevExc; +class EnotdirExc; +class EisdirExc; +class EinvalExc; +class EnfileExc; +class EmfileExc; +class EnottyExc; +class EtxtbsyExc; +class EfbigExc; +class EnospcExc; +class EspipeExc; +class ErofsExc; +class EmlinkExc; +class EpipeExc; +class EdomExc; +class ErangeExc; +class EnomsgExc; +class EidrmExc; +class EchrngExc; +class El2nsyncExc; +class El3hltExc; +class El3rstExc; +class ElnrngExc; +class EunatchExc; +class EnocsiExc; +class El2hltExc; +class EdeadlkExc; +class EnolckExc; +class EbadeExc; +class EbadrExc; +class ExfullExc; +class EnoanoExc; +class EbadrqcExc; +class EbadsltExc; +class EdeadlockExc; +class EbfontExc; +class EnostrExc; +class EnodataExc; +class EtimeExc; +class EnosrExc; +class EnonetExc; +class EnopkgExc; +class EremoteExc; +class EnolinkExc; +class EadvExc; +class EsrmntExc; +class EcommExc; +class EprotoExc; +class EmultihopExc; +class EbadmsgExc; +class EnametoolongExc; +class EoverflowExc; +class EnotuniqExc; +class EbadfdExc; +class EremchgExc; +class ElibaccExc; +class ElibbadExc; +class ElibscnExc; +class ElibmaxExc; +class ElibexecExc; +class EilseqExc; +class EnosysExc; +class EloopExc; +class ErestartExc; +class EstrpipeExc; +class EnotemptyExc; +class EusersExc; +class EnotsockExc; +class EdestaddrreqExc; +class EmsgsizeExc; +class EprototypeExc; +class EnoprotooptExc; +class EprotonosupportExc; +class EsocktnosupportExc; +class EopnotsuppExc; +class EpfnosupportExc; +class EafnosupportExc; +class EaddrinuseExc; +class EaddrnotavailExc; +class EnetdownExc; +class EnetunreachExc; +class EnetresetExc; +class EconnabortedExc; +class EconnresetExc; +class EnobufsExc; +class EisconnExc; +class EnotconnExc; +class EshutdownExc; +class EtoomanyrefsExc; +class EtimedoutExc; +class EconnrefusedExc; +class EhostdownExc; +class EhostunreachExc; +class EalreadyExc; +class EinprogressExc; +class EstaleExc; +class EioresidExc; +class EucleanExc; +class EnotnamExc; +class EnavailExc; +class EisnamExc; +class EremoteioExc; +class EinitExc; +class EremdevExc; +class EcanceledExc; +class EnolimfileExc; +class EproclimExc; +class EdisjointExc; +class EnologinExc; +class EloginlimExc; +class EgrouploopExc; +class EnoattachExc; +class EnotsupExc; +class EnoattrExc; +class EdircorruptedExc; +class EdquotExc; +class EnfsremoteExc; +class EcontrollerExc; +class EnotcontrollerExc; +class EenqueuedExc; +class EnotenqueuedExc; +class EjoinedExc; +class EnotjoinedExc; +class EnoprocExc; +class EmustrunExc; +class EnotstoppedExc; +class EclockcpuExc; +class EinvalstateExc; +class EnoexistExc; +class EendofminorExc; +class EbufsizeExc; +class EemptyExc; +class EnointrgroupExc; +class EinvalmodeExc; +class EcantextentExc; +class EinvaltimeExc; +class EdestroyedExc; + +IEX_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IEXFORWARD_H diff --git a/3rdparty/openexr/Iex/IexMacros.h b/3rdparty/openexr/Iex/IexMacros.h index aee1433f3f..5de57c9eb3 100644 --- a/3rdparty/openexr/Iex/IexMacros.h +++ b/3rdparty/openexr/Iex/IexMacros.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2018, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -52,16 +52,22 @@ // Example: // // THROW (InputExc, "Syntax error in line " << line ", " << file << "."); -// +// //---------------------------------------------------------------------------- -#define THROW(type, text) \ - do \ - { \ - std::stringstream s; \ - s << text; \ - throw type (s); \ - } \ +#include "IexExport.h" +#include "IexForward.h" + +IEX_EXPORT void iex_debugTrap(); + +#define THROW(type, text) \ + do \ + { \ + iex_debugTrap(); \ + std::stringstream _iex_throw_s; \ + _iex_throw_s << text; \ + throw type (_iex_throw_s); \ + } \ while (0) @@ -88,22 +94,22 @@ // } //---------------------------------------------------------------------------- -#define APPEND_EXC(exc, text) \ - do \ - { \ - std::stringstream s; \ - s << text; \ - exc.append (s); \ - } \ +#define APPEND_EXC(exc, text) \ + do \ + { \ + std::stringstream _iex_append_s; \ + _iex_append_s << text; \ + exc.append (_iex_append_s); \ + } \ while (0) -#define REPLACE_EXC(exc, text) \ - do \ - { \ - std::stringstream s; \ - s << text; \ - exc.assign (s); \ - } \ +#define REPLACE_EXC(exc, text) \ + do \ + { \ + std::stringstream _iex_replace_s; \ + _iex_replace_s << text; \ + exc.assign (_iex_replace_s); \ + } \ while (0) @@ -117,13 +123,13 @@ // //------------------------------------------------------------- -#define THROW_ERRNO(text) \ - do \ - { \ - std::stringstream s; \ - s << text; \ - ::Iex::throwErrnoExc (s.str()); \ - } \ +#define THROW_ERRNO(text) \ + do \ + { \ + std::stringstream _iex_throw_errno_s; \ + _iex_throw_errno_s << text; \ + ::IEX_NAMESPACE::throwErrnoExc (_iex_throw_errno_s.str()); \ + } \ while (0) @@ -132,17 +138,33 @@ // // Example: // -// ASSERT (ptr != NULL, NullExc, "Null pointer" ); +// ASSERT (ptr != 0, NullExc, "Null pointer" ); // //------------------------------------------------------------- #define ASSERT(assertion, type, text) \ do \ { \ - if ((assertion) == false) \ - THROW (type, text); \ + if( bool(assertion) == false ) \ + { \ + THROW( type, text ); \ + } \ } \ while (0) +//------------------------------------------------------------- +// A macro to throw an IEX_NAMESPACE::LogicExc if an assertion is false, +// with the text composed from the source code file, line number, +// and assertion argument text. +// +// Example: +// +// LOGIC_ASSERT (i < n); +// +//------------------------------------------------------------- +#define LOGIC_ASSERT(assertion) \ + ASSERT(assertion, \ + IEX_NAMESPACE::LogicExc, \ + __FILE__ << "(" << __LINE__ << "): logical assertion failed: " << #assertion ) #endif diff --git a/3rdparty/openexr/Iex/IexMathExc.h b/3rdparty/openexr/Iex/IexMathExc.h index 5f76ae63c0..795f500675 100644 --- a/3rdparty/openexr/Iex/IexMathExc.h +++ b/3rdparty/openexr/Iex/IexMathExc.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,7 +39,7 @@ #include "IexBaseExc.h" -namespace Iex { +IEX_INTERNAL_NAMESPACE_HEADER_ENTER //--------------------------------------------------------- // Exception classess which correspond to specific floating @@ -52,7 +52,6 @@ DEFINE_EXC (DivzeroExc, MathExc) // Division by zero DEFINE_EXC (InexactExc, MathExc) // Inexact result DEFINE_EXC (InvalidFpOpExc, MathExc) // Invalid operation +IEX_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Iex - -#endif +#endif // INCLUDED_IEXMATHEXC_H diff --git a/3rdparty/openexr/Iex/IexNamespace.h b/3rdparty/openexr/Iex/IexNamespace.h new file mode 100644 index 0000000000..bef1572283 --- /dev/null +++ b/3rdparty/openexr/Iex/IexNamespace.h @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IEXNAMESPACE_H +#define INCLUDED_IEXNAMESPACE_H + +// +// The purpose of this file is to make it possible to specify an +// IEX_INTERNAL_NAMESPACE as a preprocessor definition and have all of the +// Iex symbols defined within that namespace rather than the standard +// Iex namespace. Those symbols are made available to client code through +// the IEX_NAMESPACE in addition to the IEX_INTERNAL_NAMESPACE. +// +// To ensure source code compatibility, the IEX_NAMESPACE defaults to Iex +// and then "using namespace IEX_INTERNAL_NAMESPACE;" brings all of the +// declarations from the IEX_INTERNAL_NAMESPACE into the IEX_NAMESPACE. This +// means that client code can continue to use syntax like Iex::BaseExc, but +// at link time it will resolve to a mangled symbol based on the +// IEX_INTERNAL_NAMESPACE. +// +// As an example, if one needed to build against a newer version of Iex and +// have it run alongside an older version in the same application, it is now +// possible to use an internal namespace to prevent collisions between the +// older versions of Iex symbols and the newer ones. To do this, the +// following could be defined at build time: +// +// IEX_INTERNAL_NAMESPACE = Iex_v2 +// +// This means that declarations inside Iex headers look like this (after the +// preprocessor has done its work): +// +// namespace Iex_v2 { +// ... +// class declarations +// ... +// } +// +// namespace Iex { +// using namespace Iex_v2; +// } +// + +// +// Open Source version of this file pulls in the IlmBaseConfig.h file +// for the configure time options. +// +#include "IlmBaseConfig.h" + +#ifndef IEX_NAMESPACE +#define IEX_NAMESPACE Iex +#endif + +#ifndef IEX_INTERNAL_NAMESPACE +#define IEX_INTERNAL_NAMESPACE IEX_NAMESPACE +#endif + +// +// We need to be sure that we import the internal namespace into the public one. +// To do this, we use the small bit of code below which initially defines +// IEX_INTERNAL_NAMESPACE (so it can be referenced) and then defines +// IEX_NAMESPACE and pulls the internal symbols into the public namespace. +// + +namespace IEX_INTERNAL_NAMESPACE {} +namespace IEX_NAMESPACE { + using namespace IEX_INTERNAL_NAMESPACE; +} + +// +// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that +// future extension to the namespace mechanism is possible without changing +// project source code. +// + +#define IEX_INTERNAL_NAMESPACE_HEADER_ENTER namespace IEX_INTERNAL_NAMESPACE { +#define IEX_INTERNAL_NAMESPACE_HEADER_EXIT } + +#define IEX_INTERNAL_NAMESPACE_SOURCE_ENTER namespace IEX_INTERNAL_NAMESPACE { +#define IEX_INTERNAL_NAMESPACE_SOURCE_EXIT } + +#endif // INCLUDED_IEXNAMESPACE_H diff --git a/3rdparty/openexr/Iex/IexThrowErrnoExc.cpp b/3rdparty/openexr/Iex/IexThrowErrnoExc.cpp index 10336592ad..32e7fb2fe1 100644 --- a/3rdparty/openexr/Iex/IexThrowErrnoExc.cpp +++ b/3rdparty/openexr/Iex/IexThrowErrnoExc.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,803 +46,812 @@ #include #include -namespace Iex { +#ifdef PLATFORM_WINDOWS +#include +#endif + +IEX_INTERNAL_NAMESPACE_SOURCE_ENTER void throwErrnoExc (const std::string &text, int errnum) { +#ifdef PLATFORM_WINDOWS + if (0 != getenv("IEXDEBUGTHROW")) + DebugBreak(); +#endif + const char *entext = strerror (errnum); std::string tmp (text); std::string::size_type pos; while (std::string::npos != (pos = tmp.find ("%T"))) - tmp.replace (pos, 2, entext, strlen (entext)); + tmp.replace (pos, 2, entext, strlen (entext)); switch (errnum) { #if defined (EPERM) - case EPERM: - throw EpermExc (tmp); + case EPERM: + throw EpermExc (tmp); #endif #if defined (ENOENT) - case ENOENT: - throw EnoentExc (tmp); + case ENOENT: + throw EnoentExc (tmp); #endif #if defined (ESRCH) - case ESRCH: - throw EsrchExc (tmp); + case ESRCH: + throw EsrchExc (tmp); #endif #if defined (EINTR) - case EINTR: - throw EintrExc (tmp); + case EINTR: + throw EintrExc (tmp); #endif #if defined (EIO) - case EIO: - throw EioExc (tmp); + case EIO: + throw EioExc (tmp); #endif #if defined (ENXIO) - case ENXIO: - throw EnxioExc (tmp); + case ENXIO: + throw EnxioExc (tmp); #endif #if defined (E2BIG) - case E2BIG: - throw E2bigExc (tmp); + case E2BIG: + throw E2bigExc (tmp); #endif #if defined (ENOEXEC) - case ENOEXEC: - throw EnoexecExc (tmp); + case ENOEXEC: + throw EnoexecExc (tmp); #endif #if defined (EBADF) - case EBADF: - throw EbadfExc (tmp); + case EBADF: + throw EbadfExc (tmp); #endif #if defined (ECHILD) - case ECHILD: - throw EchildExc (tmp); + case ECHILD: + throw EchildExc (tmp); #endif #if defined (EAGAIN) - case EAGAIN: - throw EagainExc (tmp); + case EAGAIN: + throw EagainExc (tmp); #endif #if defined (ENOMEM) - case ENOMEM: - throw EnomemExc (tmp); + case ENOMEM: + throw EnomemExc (tmp); #endif #if defined (EACCES) - case EACCES: - throw EaccesExc (tmp); + case EACCES: + throw EaccesExc (tmp); #endif #if defined (EFAULT) - case EFAULT: - throw EfaultExc (tmp); + case EFAULT: + throw EfaultExc (tmp); #endif #if defined (ENOTBLK) - case ENOTBLK: - throw EnotblkExc (tmp); + case ENOTBLK: + throw EnotblkExc (tmp); #endif #if defined (EBUSY) - case EBUSY: - throw EbusyExc (tmp); + case EBUSY: + throw EbusyExc (tmp); #endif #if defined (EEXIST) - case EEXIST: - throw EexistExc (tmp); + case EEXIST: + throw EexistExc (tmp); #endif #if defined (EXDEV) - case EXDEV: - throw ExdevExc (tmp); + case EXDEV: + throw ExdevExc (tmp); #endif #if defined (ENODEV) - case ENODEV: - throw EnodevExc (tmp); + case ENODEV: + throw EnodevExc (tmp); #endif #if defined (ENOTDIR) - case ENOTDIR: - throw EnotdirExc (tmp); + case ENOTDIR: + throw EnotdirExc (tmp); #endif #if defined (EISDIR) - case EISDIR: - throw EisdirExc (tmp); + case EISDIR: + throw EisdirExc (tmp); #endif #if defined (EINVAL) - case EINVAL: - throw EinvalExc (tmp); + case EINVAL: + throw EinvalExc (tmp); #endif #if defined (ENFILE) - case ENFILE: - throw EnfileExc (tmp); + case ENFILE: + throw EnfileExc (tmp); #endif #if defined (EMFILE) - case EMFILE: - throw EmfileExc (tmp); + case EMFILE: + throw EmfileExc (tmp); #endif #if defined (ENOTTY) - case ENOTTY: - throw EnottyExc (tmp); + case ENOTTY: + throw EnottyExc (tmp); #endif #if defined (ETXTBSY) - case ETXTBSY: - throw EtxtbsyExc (tmp); + case ETXTBSY: + throw EtxtbsyExc (tmp); #endif #if defined (EFBIG) - case EFBIG: - throw EfbigExc (tmp); + case EFBIG: + throw EfbigExc (tmp); #endif #if defined (ENOSPC) - case ENOSPC: - throw EnospcExc (tmp); + case ENOSPC: + throw EnospcExc (tmp); #endif #if defined (ESPIPE) - case ESPIPE: - throw EspipeExc (tmp); + case ESPIPE: + throw EspipeExc (tmp); #endif #if defined (EROFS) - case EROFS: - throw ErofsExc (tmp); + case EROFS: + throw ErofsExc (tmp); #endif #if defined (EMLINK) - case EMLINK: - throw EmlinkExc (tmp); + case EMLINK: + throw EmlinkExc (tmp); #endif #if defined (EPIPE) - case EPIPE: - throw EpipeExc (tmp); + case EPIPE: + throw EpipeExc (tmp); #endif #if defined (EDOM) - case EDOM: - throw EdomExc (tmp); + case EDOM: + throw EdomExc (tmp); #endif #if defined (ERANGE) - case ERANGE: - throw ErangeExc (tmp); + case ERANGE: + throw ErangeExc (tmp); #endif #if defined (ENOMSG) - case ENOMSG: - throw EnomsgExc (tmp); + case ENOMSG: + throw EnomsgExc (tmp); #endif #if defined (EIDRM) - case EIDRM: - throw EidrmExc (tmp); + case EIDRM: + throw EidrmExc (tmp); #endif #if defined (ECHRNG) - case ECHRNG: - throw EchrngExc (tmp); + case ECHRNG: + throw EchrngExc (tmp); #endif #if defined (EL2NSYNC) - case EL2NSYNC: - throw El2nsyncExc (tmp); + case EL2NSYNC: + throw El2nsyncExc (tmp); #endif #if defined (EL3HLT) - case EL3HLT: - throw El3hltExc (tmp); + case EL3HLT: + throw El3hltExc (tmp); #endif #if defined (EL3RST) - case EL3RST: - throw El3rstExc (tmp); + case EL3RST: + throw El3rstExc (tmp); #endif #if defined (ELNRNG) - case ELNRNG: - throw ElnrngExc (tmp); + case ELNRNG: + throw ElnrngExc (tmp); #endif #if defined (EUNATCH) - case EUNATCH: - throw EunatchExc (tmp); + case EUNATCH: + throw EunatchExc (tmp); #endif #if defined (ENOSCI) - case ENOCSI: - throw EnocsiExc (tmp); + case ENOCSI: + throw EnocsiExc (tmp); #endif #if defined (EL2HLT) - case EL2HLT: - throw El2hltExc (tmp); + case EL2HLT: + throw El2hltExc (tmp); #endif #if defined (EDEADLK) - case EDEADLK: - throw EdeadlkExc (tmp); + case EDEADLK: + throw EdeadlkExc (tmp); #endif #if defined (ENOLCK) - case ENOLCK: - throw EnolckExc (tmp); + case ENOLCK: + throw EnolckExc (tmp); #endif #if defined (EBADE) - case EBADE: - throw EbadeExc (tmp); + case EBADE: + throw EbadeExc (tmp); #endif #if defined (EBADR) - case EBADR: - throw EbadrExc (tmp); + case EBADR: + throw EbadrExc (tmp); #endif #if defined (EXFULL) - case EXFULL: - throw ExfullExc (tmp); + case EXFULL: + throw ExfullExc (tmp); #endif #if defined (ENOANO) - case ENOANO: - throw EnoanoExc (tmp); + case ENOANO: + throw EnoanoExc (tmp); #endif #if defined (EBADRQC) - case EBADRQC: - throw EbadrqcExc (tmp); + case EBADRQC: + throw EbadrqcExc (tmp); #endif #if defined (EBADSLT) - case EBADSLT: - throw EbadsltExc (tmp); + case EBADSLT: + throw EbadsltExc (tmp); #endif #if defined (EDEADLOCK) && defined (EDEADLK) - #if EDEADLOCK != EDEADLK - case EDEADLOCK: - throw EdeadlockExc (tmp); - #endif + #if EDEADLOCK != EDEADLK + case EDEADLOCK: + throw EdeadlockExc (tmp); + #endif #elif defined (EDEADLOCK) - case EDEADLOCK: - throw EdeadlockExc (tmp); + case EDEADLOCK: + throw EdeadlockExc (tmp); #endif #if defined (EBFONT) - case EBFONT: - throw EbfontExc (tmp); + case EBFONT: + throw EbfontExc (tmp); #endif #if defined (ENOSTR) - case ENOSTR: - throw EnostrExc (tmp); + case ENOSTR: + throw EnostrExc (tmp); #endif #if defined (ENODATA) - case ENODATA: - throw EnodataExc (tmp); + case ENODATA: + throw EnodataExc (tmp); #endif #if defined (ETIME) - case ETIME: - throw EtimeExc (tmp); + case ETIME: + throw EtimeExc (tmp); #endif #if defined (ENOSR) - case ENOSR: - throw EnosrExc (tmp); + case ENOSR: + throw EnosrExc (tmp); #endif #if defined (ENONET) - case ENONET: - throw EnonetExc (tmp); + case ENONET: + throw EnonetExc (tmp); #endif #if defined (ENOPKG) - case ENOPKG: - throw EnopkgExc (tmp); + case ENOPKG: + throw EnopkgExc (tmp); #endif #if defined (EREMOTE) - case EREMOTE: - throw EremoteExc (tmp); + case EREMOTE: + throw EremoteExc (tmp); #endif #if defined (ENOLINK) - case ENOLINK: - throw EnolinkExc (tmp); + case ENOLINK: + throw EnolinkExc (tmp); #endif #if defined (EADV) - case EADV: - throw EadvExc (tmp); + case EADV: + throw EadvExc (tmp); #endif #if defined (ESRMNT) - case ESRMNT: - throw EsrmntExc (tmp); + case ESRMNT: + throw EsrmntExc (tmp); #endif #if defined (ECOMM) - case ECOMM: - throw EcommExc (tmp); + case ECOMM: + throw EcommExc (tmp); #endif #if defined (EPROTO) - case EPROTO: - throw EprotoExc (tmp); + case EPROTO: + throw EprotoExc (tmp); #endif #if defined (EMULTIHOP) - case EMULTIHOP: - throw EmultihopExc (tmp); + case EMULTIHOP: + throw EmultihopExc (tmp); #endif #if defined (EBADMSG) - case EBADMSG: - throw EbadmsgExc (tmp); + case EBADMSG: + throw EbadmsgExc (tmp); #endif #if defined (ENAMETOOLONG) - case ENAMETOOLONG: - throw EnametoolongExc (tmp); + case ENAMETOOLONG: + throw EnametoolongExc (tmp); #endif #if defined (EOVERFLOW) - case EOVERFLOW: - throw EoverflowExc (tmp); + case EOVERFLOW: + throw EoverflowExc (tmp); #endif #if defined (ENOTUNIQ) - case ENOTUNIQ: - throw EnotuniqExc (tmp); + case ENOTUNIQ: + throw EnotuniqExc (tmp); #endif #if defined (EBADFD) - case EBADFD: - throw EbadfdExc (tmp); + case EBADFD: + throw EbadfdExc (tmp); #endif #if defined (EREMCHG) - case EREMCHG: - throw EremchgExc (tmp); + case EREMCHG: + throw EremchgExc (tmp); #endif #if defined (ELIBACC) - case ELIBACC: - throw ElibaccExc (tmp); + case ELIBACC: + throw ElibaccExc (tmp); #endif #if defined (ELIBBAD) - case ELIBBAD: - throw ElibbadExc (tmp); + case ELIBBAD: + throw ElibbadExc (tmp); #endif #if defined (ELIBSCN) - case ELIBSCN: - throw ElibscnExc (tmp); + case ELIBSCN: + throw ElibscnExc (tmp); #endif #if defined (ELIBMAX) - case ELIBMAX: - throw ElibmaxExc (tmp); + case ELIBMAX: + throw ElibmaxExc (tmp); #endif #if defined (ELIBEXEC) - case ELIBEXEC: - throw ElibexecExc (tmp); + case ELIBEXEC: + throw ElibexecExc (tmp); #endif #if defined (EILSEQ) - case EILSEQ: - throw EilseqExc (tmp); + case EILSEQ: + throw EilseqExc (tmp); #endif #if defined (ENOSYS) - case ENOSYS: - throw EnosysExc (tmp); + case ENOSYS: + throw EnosysExc (tmp); #endif #if defined (ELOOP) - case ELOOP: - throw EloopExc (tmp); + case ELOOP: + throw EloopExc (tmp); #endif #if defined (ERESTART) - case ERESTART: - throw ErestartExc (tmp); + case ERESTART: + throw ErestartExc (tmp); #endif #if defined (ESTRPIPE) - case ESTRPIPE: - throw EstrpipeExc (tmp); + case ESTRPIPE: + throw EstrpipeExc (tmp); #endif #if defined (ENOTEMPTY) - case ENOTEMPTY: - throw EnotemptyExc (tmp); + case ENOTEMPTY: + throw EnotemptyExc (tmp); #endif #if defined (EUSERS) - case EUSERS: - throw EusersExc (tmp); + case EUSERS: + throw EusersExc (tmp); #endif #if defined (ENOTSOCK) - case ENOTSOCK: - throw EnotsockExc (tmp); + case ENOTSOCK: + throw EnotsockExc (tmp); #endif #if defined (EDESTADDRREQ) - case EDESTADDRREQ: - throw EdestaddrreqExc (tmp); + case EDESTADDRREQ: + throw EdestaddrreqExc (tmp); #endif #if defined (EMSGSIZE) - case EMSGSIZE: - throw EmsgsizeExc (tmp); + case EMSGSIZE: + throw EmsgsizeExc (tmp); #endif #if defined (EPROTOTYPE) - case EPROTOTYPE: - throw EprototypeExc (tmp); + case EPROTOTYPE: + throw EprototypeExc (tmp); #endif #if defined (ENOPROTOOPT) - case ENOPROTOOPT: - throw EnoprotooptExc (tmp); + case ENOPROTOOPT: + throw EnoprotooptExc (tmp); #endif #if defined (EPROTONOSUPPORT) - case EPROTONOSUPPORT: - throw EprotonosupportExc (tmp); + case EPROTONOSUPPORT: + throw EprotonosupportExc (tmp); #endif #if defined (ESOCKTNOSUPPORT) - case ESOCKTNOSUPPORT: - throw EsocktnosupportExc (tmp); + case ESOCKTNOSUPPORT: + throw EsocktnosupportExc (tmp); #endif #if defined (EOPNOTSUPP) - case EOPNOTSUPP: - throw EopnotsuppExc (tmp); + case EOPNOTSUPP: + throw EopnotsuppExc (tmp); #endif #if defined (EPFNOSUPPORT) - case EPFNOSUPPORT: - throw EpfnosupportExc (tmp); + case EPFNOSUPPORT: + throw EpfnosupportExc (tmp); #endif #if defined (EAFNOSUPPORT) - case EAFNOSUPPORT: - throw EafnosupportExc (tmp); + case EAFNOSUPPORT: + throw EafnosupportExc (tmp); #endif #if defined (EADDRINUSE) - case EADDRINUSE: - throw EaddrinuseExc (tmp); + case EADDRINUSE: + throw EaddrinuseExc (tmp); #endif #if defined (EADDRNOTAVAIL) - case EADDRNOTAVAIL: - throw EaddrnotavailExc (tmp); + case EADDRNOTAVAIL: + throw EaddrnotavailExc (tmp); #endif #if defined (ENETDOWN) - case ENETDOWN: - throw EnetdownExc (tmp); + case ENETDOWN: + throw EnetdownExc (tmp); #endif #if defined (ENETUNREACH) - case ENETUNREACH: - throw EnetunreachExc (tmp); + case ENETUNREACH: + throw EnetunreachExc (tmp); #endif #if defined (ENETRESET) - case ENETRESET: - throw EnetresetExc (tmp); + case ENETRESET: + throw EnetresetExc (tmp); #endif #if defined (ECONNABORTED) - case ECONNABORTED: - throw EconnabortedExc (tmp); + case ECONNABORTED: + throw EconnabortedExc (tmp); #endif #if defined (ECONNRESET) - case ECONNRESET: - throw EconnresetExc (tmp); + case ECONNRESET: + throw EconnresetExc (tmp); #endif #if defined (ENOBUFS) - case ENOBUFS: - throw EnobufsExc (tmp); + case ENOBUFS: + throw EnobufsExc (tmp); #endif #if defined (EISCONN) - case EISCONN: - throw EisconnExc (tmp); + case EISCONN: + throw EisconnExc (tmp); #endif #if defined (ENOTCONN) - case ENOTCONN: - throw EnotconnExc (tmp); + case ENOTCONN: + throw EnotconnExc (tmp); #endif #if defined (ESHUTDOWN) - case ESHUTDOWN: - throw EshutdownExc (tmp); + case ESHUTDOWN: + throw EshutdownExc (tmp); #endif #if defined (ETOOMANYREFS) - case ETOOMANYREFS: - throw EtoomanyrefsExc (tmp); + case ETOOMANYREFS: + throw EtoomanyrefsExc (tmp); #endif #if defined (ETIMEDOUT) - case ETIMEDOUT: - throw EtimedoutExc (tmp); + case ETIMEDOUT: + throw EtimedoutExc (tmp); #endif #if defined (ECONNREFUSED) - case ECONNREFUSED: - throw EconnrefusedExc (tmp); + case ECONNREFUSED: + throw EconnrefusedExc (tmp); #endif #if defined (EHOSTDOWN) - case EHOSTDOWN: - throw EhostdownExc (tmp); + case EHOSTDOWN: + throw EhostdownExc (tmp); #endif #if defined (EHOSTUNREACH) - case EHOSTUNREACH: - throw EhostunreachExc (tmp); + case EHOSTUNREACH: + throw EhostunreachExc (tmp); #endif #if defined (EALREADY) - case EALREADY: - throw EalreadyExc (tmp); + case EALREADY: + throw EalreadyExc (tmp); #endif #if defined (EINPROGRESS) - case EINPROGRESS: - throw EinprogressExc (tmp); + case EINPROGRESS: + throw EinprogressExc (tmp); #endif #if defined (ESTALE) - case ESTALE: - throw EstaleExc (tmp); + case ESTALE: + throw EstaleExc (tmp); #endif #if defined (EIORESID) - case EIORESID: - throw EioresidExc (tmp); + case EIORESID: + throw EioresidExc (tmp); #endif #if defined (EUCLEAN) - case EUCLEAN: - throw EucleanExc (tmp); + case EUCLEAN: + throw EucleanExc (tmp); #endif #if defined (ENOTNAM) - case ENOTNAM: - throw EnotnamExc (tmp); + case ENOTNAM: + throw EnotnamExc (tmp); #endif #if defined (ENAVAIL) - case ENAVAIL: - throw EnavailExc (tmp); + case ENAVAIL: + throw EnavailExc (tmp); #endif #if defined (EISNAM) - case EISNAM: - throw EisnamExc (tmp); + case EISNAM: + throw EisnamExc (tmp); #endif #if defined (EREMOTEIO) - case EREMOTEIO: - throw EremoteioExc (tmp); + case EREMOTEIO: + throw EremoteioExc (tmp); #endif #if defined (EINIT) - case EINIT: - throw EinitExc (tmp); + case EINIT: + throw EinitExc (tmp); #endif #if defined (EREMDEV) - case EREMDEV: - throw EremdevExc (tmp); + case EREMDEV: + throw EremdevExc (tmp); #endif #if defined (ECANCELED) - case ECANCELED: - throw EcanceledExc (tmp); + case ECANCELED: + throw EcanceledExc (tmp); #endif #if defined (ENOLIMFILE) - case ENOLIMFILE: - throw EnolimfileExc (tmp); + case ENOLIMFILE: + throw EnolimfileExc (tmp); #endif #if defined (EPROCLIM) - case EPROCLIM: - throw EproclimExc (tmp); + case EPROCLIM: + throw EproclimExc (tmp); #endif #if defined (EDISJOINT) - case EDISJOINT: - throw EdisjointExc (tmp); + case EDISJOINT: + throw EdisjointExc (tmp); #endif #if defined (ENOLOGIN) - case ENOLOGIN: - throw EnologinExc (tmp); + case ENOLOGIN: + throw EnologinExc (tmp); #endif #if defined (ELOGINLIM) - case ELOGINLIM: - throw EloginlimExc (tmp); + case ELOGINLIM: + throw EloginlimExc (tmp); #endif #if defined (EGROUPLOOP) - case EGROUPLOOP: - throw EgrouploopExc (tmp); + case EGROUPLOOP: + throw EgrouploopExc (tmp); #endif #if defined (ENOATTACH) - case ENOATTACH: - throw EnoattachExc (tmp); + case ENOATTACH: + throw EnoattachExc (tmp); #endif #if defined (ENOTSUP) && defined (EOPNOTSUPP) - #if ENOTSUP != EOPNOTSUPP - case ENOTSUP: - throw EnotsupExc (tmp); - #endif + #if ENOTSUP != EOPNOTSUPP + case ENOTSUP: + throw EnotsupExc (tmp); + #endif #elif defined (ENOTSUP) - case ENOTSUP: - throw EnotsupExc (tmp); + case ENOTSUP: + throw EnotsupExc (tmp); #endif #if defined (ENOATTR) - case ENOATTR: - throw EnoattrExc (tmp); + case ENOATTR: + throw EnoattrExc (tmp); #endif #if defined (EDIRCORRUPTED) - case EDIRCORRUPTED: - throw EdircorruptedExc (tmp); + case EDIRCORRUPTED: + throw EdircorruptedExc (tmp); #endif #if defined (EDQUOT) - case EDQUOT: - throw EdquotExc (tmp); + case EDQUOT: + throw EdquotExc (tmp); #endif #if defined (ENFSREMOTE) - case ENFSREMOTE: - throw EnfsremoteExc (tmp); + case ENFSREMOTE: + throw EnfsremoteExc (tmp); #endif #if defined (ECONTROLLER) - case ECONTROLLER: - throw EcontrollerExc (tmp); + case ECONTROLLER: + throw EcontrollerExc (tmp); #endif #if defined (ENOTCONTROLLER) - case ENOTCONTROLLER: - throw EnotcontrollerExc (tmp); + case ENOTCONTROLLER: + throw EnotcontrollerExc (tmp); #endif #if defined (EENQUEUED) - case EENQUEUED: - throw EenqueuedExc (tmp); + case EENQUEUED: + throw EenqueuedExc (tmp); #endif #if defined (ENOTENQUEUED) - case ENOTENQUEUED: - throw EnotenqueuedExc (tmp); + case ENOTENQUEUED: + throw EnotenqueuedExc (tmp); #endif #if defined (EJOINED) - case EJOINED: - throw EjoinedExc (tmp); + case EJOINED: + throw EjoinedExc (tmp); #endif #if defined (ENOTJOINED) - case ENOTJOINED: - throw EnotjoinedExc (tmp); + case ENOTJOINED: + throw EnotjoinedExc (tmp); #endif #if defined (ENOPROC) - case ENOPROC: - throw EnoprocExc (tmp); + case ENOPROC: + throw EnoprocExc (tmp); #endif #if defined (EMUSTRUN) - case EMUSTRUN: - throw EmustrunExc (tmp); + case EMUSTRUN: + throw EmustrunExc (tmp); #endif #if defined (ENOTSTOPPED) - case ENOTSTOPPED: - throw EnotstoppedExc (tmp); + case ENOTSTOPPED: + throw EnotstoppedExc (tmp); #endif #if defined (ECLOCKCPU) - case ECLOCKCPU: - throw EclockcpuExc (tmp); + case ECLOCKCPU: + throw EclockcpuExc (tmp); #endif #if defined (EINVALSTATE) - case EINVALSTATE: - throw EinvalstateExc (tmp); + case EINVALSTATE: + throw EinvalstateExc (tmp); #endif #if defined (ENOEXIST) - case ENOEXIST: - throw EnoexistExc (tmp); + case ENOEXIST: + throw EnoexistExc (tmp); #endif #if defined (EENDOFMINOR) - case EENDOFMINOR: - throw EendofminorExc (tmp); + case EENDOFMINOR: + throw EendofminorExc (tmp); #endif #if defined (EBUFSIZE) - case EBUFSIZE: - throw EbufsizeExc (tmp); + case EBUFSIZE: + throw EbufsizeExc (tmp); #endif #if defined (EEMPTY) - case EEMPTY: - throw EemptyExc (tmp); + case EEMPTY: + throw EemptyExc (tmp); #endif #if defined (ENOINTRGROUP) - case ENOINTRGROUP: - throw EnointrgroupExc (tmp); + case ENOINTRGROUP: + throw EnointrgroupExc (tmp); #endif #if defined (EINVALMODE) - case EINVALMODE: - throw EinvalmodeExc (tmp); + case EINVALMODE: + throw EinvalmodeExc (tmp); #endif #if defined (ECANTEXTENT) - case ECANTEXTENT: - throw EcantextentExc (tmp); + case ECANTEXTENT: + throw EcantextentExc (tmp); #endif #if defined (EINVALTIME) - case EINVALTIME: - throw EinvaltimeExc (tmp); + case EINVALTIME: + throw EinvaltimeExc (tmp); #endif #if defined (EDESTROYED) - case EDESTROYED: - throw EdestroyedExc (tmp); + case EDESTROYED: + throw EdestroyedExc (tmp); #endif } @@ -855,5 +864,10 @@ void throwErrnoExc (const std::string &text) throwErrnoExc (text, errno); } +void throwErrnoExc() +{ + std::string txt = "%T."; + throwErrnoExc (txt); +} -} // namespace Iex +IEX_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/Iex/IexThrowErrnoExc.h b/3rdparty/openexr/Iex/IexThrowErrnoExc.h index 2c718ac3ca..224ed2bf58 100644 --- a/3rdparty/openexr/Iex/IexThrowErrnoExc.h +++ b/3rdparty/openexr/Iex/IexThrowErrnoExc.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,8 +44,9 @@ //---------------------------------------------------------- #include "IexBaseExc.h" +#include "IexExport.h" -namespace Iex { +IEX_INTERNAL_NAMESPACE_HEADER_ENTER //-------------------------------------------------------------------------- @@ -56,7 +57,7 @@ namespace Iex { // "%T" have been replaced with the output of strerror(oserror()). // // Example: -// +// // If opening file /tmp/output failed with an ENOENT error code, // calling // @@ -87,10 +88,10 @@ namespace Iex { // //-------------------------------------------------------------------------- -void throwErrnoExc (const std::string &txt, int errnum); -void throwErrnoExc (const std::string &txt = "%T." /*, int errnum = oserror() */); - +IEX_EXPORT void throwErrnoExc(const std::string &txt, int errnum); +IEX_EXPORT void throwErrnoExc(const std::string &txt); +IEX_EXPORT void throwErrnoExc(); -} // namespace Iex +IEX_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IEXTHROWERRNOEXC_H diff --git a/3rdparty/openexr/IlmBaseConfig.h.cmakein b/3rdparty/openexr/IlmBaseConfig.h.cmakein index ebbd5392bc..b1f94db8a8 100644 --- a/3rdparty/openexr/IlmBaseConfig.h.cmakein +++ b/3rdparty/openexr/IlmBaseConfig.h.cmakein @@ -1,3 +1,15 @@ +#cmakedefine PLATFORM_WINDOWS + +// +// Define and set to 1 if the target system has c++11/14 support +// and you want IlmBase to NOT use it's features +// + +#cmakedefine01 ILMBASE_FORCE_CXX03 +#if ILMBASE_FORCE_CXX03 == 0 +#undef ILMBASE_FORCE_CXX03 +#endif + // // Define and set to 1 if the target system has POSIX thread support // and you want IlmBase to use it for multithreaded file I/O. @@ -13,18 +25,59 @@ #cmakedefine01 HAVE_POSIX_SEMAPHORES -#undef HAVE_UCONTEXT_H + +#cmakedefine HAVE_UCONTEXT_H + + +// +// Dealing with FPEs +// +#cmakedefine01 ILMBASE_HAVE_CONTROL_REGISTER_SUPPORT + + +// +// Define and set to 1 if the target system has support for large +// stack sizes. +// + +#cmakedefine ILMBASE_HAVE_LARGE_STACK + +// +// Current (internal) library namepace name and corresponding public +// client namespaces. +// +#define ILMBASE_INTERNAL_NAMESPACE_CUSTOM @ILMBASE_INTERNAL_NAMESPACE_CUSTOM@ +#define IMATH_INTERNAL_NAMESPACE @IMATH_INTERNAL_NAMESPACE@ +#define IEX_INTERNAL_NAMESPACE @IEX_INTERNAL_NAMESPACE@ +#define ILMTHREAD_INTERNAL_NAMESPACE @ILMTHREAD_INTERNAL_NAMESPACE@ + +#define ILMBASE_NAMESPACE_CUSTOM @ILMBASE_NAMESPACE_CUSTOM@ +#define IMATH_NAMESPACE @IMATH_NAMESPACE@ +#define IEX_NAMESPACE @IEX_NAMESPACE@ +#define ILMTHREAD_NAMESPACE @ILMTHREAD_NAMESPACE@ + // // Define and set to 1 if the target system has support for large // stack sizes. // -#undef ILMBASE_HAVE_LARGE_STACK +#cmakedefine ILMBASE_HAVE_LARGE_STACK // -// Version string for runtime access +// Version information // -#define ILMBASE_VERSION_STRING "1.0.3" -#define ILMBASE_PACKAGE_STRING "IlmBase 1.0.3" +#define ILMBASE_VERSION_STRING @ILMBASE_VERSION_STRING@ +#define ILMBASE_PACKAGE_STRING @ILMBASE_PACKAGE_STRING@ + +#define ILMBASE_VERSION_MAJOR @ILMBASE_VERSION_MAJOR@ +#define ILMBASE_VERSION_MINOR @ILMBASE_VERSION_MINOR@ +#define ILMBASE_VERSION_PATCH @ILMBASE_VERSION_PATCH@ + +// Version as a single hex number, e.g. 0x01000300 == 1.0.3 +#define ILMBASE_VERSION_HEX ((ILMBASE_VERSION_MAJOR << 24) | \ + (ILMBASE_VERSION_MINOR << 16) | \ + (ILMBASE_VERSION_PATCH << 8)) + + diff --git a/3rdparty/openexr/IlmImf/ImfAcesFile.cpp b/3rdparty/openexr/IlmImf/ImfAcesFile.cpp index 9418b9d2a1..8f33fb0df7 100644 --- a/3rdparty/openexr/IlmImf/ImfAcesFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfAcesFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2007, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -35,30 +35,31 @@ //----------------------------------------------------------------------------- // // ACES image file I/O. -// +// //----------------------------------------------------------------------------- #include #include #include #include -#include // for std::max() +#include using namespace std; -using namespace Imath; -using namespace Iex; +using namespace IMATH_NAMESPACE; +using namespace IEX_NAMESPACE; +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER const Chromaticities & acesChromaticities () { - static const Chromaticities acesChr - (V2f (0.73470, 0.26530), // red - V2f (0.00000, 1.00000), // green - V2f (0.00010, -0.07700), // blue - V2f (0.32168, 0.33767)); // white + static const Chromaticities acesChr + (V2f (0.73470, 0.26530), // red + V2f (0.00000, 1.00000), // green + V2f (0.00010, -0.07700), // blue + V2f (0.32168, 0.33767)); // white return acesChr; } @@ -102,10 +103,10 @@ checkCompression (Compression compression) case NO_COMPRESSION: case PIZ_COMPRESSION: case B44A_COMPRESSION: - break; + break; default: - throw ArgExc ("Invalid compression type for ACES file."); + throw ArgExc ("Invalid compression type for ACES file."); } } @@ -127,16 +128,16 @@ AcesOutputFile::AcesOutputFile addAdoptedNeutral (newHeader, acesChromaticities().white); _data->rgbaFile = new RgbaOutputFile (name.c_str(), - newHeader, - rgbaChannels, - numThreads); + newHeader, + rgbaChannels, + numThreads); _data->rgbaFile->setYCRounding (7, 6); } AcesOutputFile::AcesOutputFile - (OStream &os, + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header, RgbaChannels rgbaChannels, int numThreads) @@ -150,9 +151,9 @@ AcesOutputFile::AcesOutputFile addAdoptedNeutral (newHeader, acesChromaticities().white); _data->rgbaFile = new RgbaOutputFile (os, - header, - rgbaChannels, - numThreads); + header, + rgbaChannels, + numThreads); _data->rgbaFile->setYCRounding (7, 6); } @@ -160,11 +161,11 @@ AcesOutputFile::AcesOutputFile AcesOutputFile::AcesOutputFile (const std::string &name, - const Imath::Box2i &displayWindow, - const Imath::Box2i &dataWindow, + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow, RgbaChannels rgbaChannels, float pixelAspectRatio, - const Imath::V2f screenWindowCenter, + const IMATH_NAMESPACE::V2f screenWindowCenter, float screenWindowWidth, LineOrder lineOrder, Compression compression, @@ -175,20 +176,20 @@ AcesOutputFile::AcesOutputFile checkCompression (compression); Header newHeader (displayWindow, - dataWindow.isEmpty()? displayWindow: dataWindow, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + dataWindow.isEmpty()? displayWindow: dataWindow, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); addChromaticities (newHeader, acesChromaticities()); addAdoptedNeutral (newHeader, acesChromaticities().white); _data->rgbaFile = new RgbaOutputFile (name.c_str(), - newHeader, - rgbaChannels, - numThreads); + newHeader, + rgbaChannels, + numThreads); _data->rgbaFile->setYCRounding (7, 6); } @@ -200,7 +201,7 @@ AcesOutputFile::AcesOutputFile int height, RgbaChannels rgbaChannels, float pixelAspectRatio, - const Imath::V2f screenWindowCenter, + const IMATH_NAMESPACE::V2f screenWindowCenter, float screenWindowWidth, LineOrder lineOrder, Compression compression, @@ -211,20 +212,20 @@ AcesOutputFile::AcesOutputFile checkCompression (compression); Header newHeader (width, - height, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + height, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); addChromaticities (newHeader, acesChromaticities()); addAdoptedNeutral (newHeader, acesChromaticities().white); _data->rgbaFile = new RgbaOutputFile (name.c_str(), - newHeader, - rgbaChannels, - numThreads); + newHeader, + rgbaChannels, + numThreads); _data->rgbaFile->setYCRounding (7, 6); } @@ -236,7 +237,7 @@ AcesOutputFile::~AcesOutputFile () } -void +void AcesOutputFile::setFrameBuffer (const Rgba *base, size_t xStride, @@ -246,14 +247,14 @@ AcesOutputFile::setFrameBuffer } -void +void AcesOutputFile::writePixels (int numScanLines) { _data->rgbaFile->writePixels (numScanLines); } -int +int AcesOutputFile::currentScanLine () const { return _data->rgbaFile->currentScanLine(); @@ -267,49 +268,49 @@ AcesOutputFile::header () const } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & AcesOutputFile::displayWindow () const { return _data->rgbaFile->displayWindow(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & AcesOutputFile::dataWindow () const { return _data->rgbaFile->dataWindow(); } -float +float AcesOutputFile::pixelAspectRatio () const { return _data->rgbaFile->pixelAspectRatio(); } -const Imath::V2f +const IMATH_NAMESPACE::V2f AcesOutputFile::screenWindowCenter () const { return _data->rgbaFile->screenWindowCenter(); } -float +float AcesOutputFile::screenWindowWidth () const { return _data->rgbaFile->screenWindowWidth(); } -LineOrder +LineOrder AcesOutputFile::lineOrder () const { return _data->rgbaFile->lineOrder(); } -Compression +Compression AcesOutputFile::compression () const { return _data->rgbaFile->compression(); @@ -323,7 +324,7 @@ AcesOutputFile::channels () const } -void +void AcesOutputFile::updatePreviewImage (const PreviewRgba pixels[]) { _data->rgbaFile->updatePreviewImage (pixels); @@ -379,28 +380,28 @@ AcesInputFile::Data::initColorConversion () Chromaticities fileChr; if (hasChromaticities (header)) - fileChr = chromaticities (header); + fileChr = chromaticities (header); V2f fileNeutral = fileChr.white; if (hasAdoptedNeutral (header)) - fileNeutral = adoptedNeutral (header); + fileNeutral = adoptedNeutral (header); const Chromaticities acesChr = acesChromaticities(); V2f acesNeutral = acesChr.white; if (fileChr.red == acesChr.red && - fileChr.green == acesChr.green && - fileChr.blue == acesChr.blue && - fileChr.white == acesChr.white && - fileNeutral == acesNeutral) + fileChr.green == acesChr.green && + fileChr.blue == acesChr.blue && + fileChr.white == acesChr.white && + fileNeutral == acesNeutral) { - // - // The file already contains ACES data, - // color conversion is not necessary. + // + // The file already contains ACES data, + // color conversion is not necessary. - return; + return; } mustConvertColor = true; @@ -419,16 +420,16 @@ AcesInputFile::Data::initColorConversion () // static const M44f bradfordCPM - (0.895100, -0.750200, 0.038900, 0.000000, - 0.266400, 1.713500, -0.068500, 0.000000, - -0.161400, 0.036700, 1.029600, 0.000000, - 0.000000, 0.000000, 0.000000, 1.000000); + (0.895100, -0.750200, 0.038900, 0.000000, + 0.266400, 1.713500, -0.068500, 0.000000, + -0.161400, 0.036700, 1.029600, 0.000000, + 0.000000, 0.000000, 0.000000, 1.000000); const static M44f inverseBradfordCPM - (0.986993, 0.432305, -0.008529, 0.000000, - -0.147054, 0.518360, 0.040043, 0.000000, - 0.159963, 0.049291, 0.968487, 0.000000, - 0.000000, 0.000000, 0.000000, 1.000000); + (0.986993, 0.432305, -0.008529, 0.000000, + -0.147054, 0.518360, 0.040043, 0.000000, + 0.159963, 0.049291, 0.968487, 0.000000, + 0.000000, 0.000000, 0.000000, 1.000000); // // Convert the white points of the two RGB spaces to XYZ @@ -447,16 +448,16 @@ AcesInputFile::Data::initColorConversion () // V3f ratio ((acesNeutralXYZ * bradfordCPM) / - (fileNeutralXYZ * bradfordCPM)); + (fileNeutralXYZ * bradfordCPM)); M44f ratioMat (ratio[0], 0, 0, 0, - 0, ratio[1], 0, 0, - 0, 0, ratio[2], 0, - 0, 0, 0, 1); + 0, ratio[1], 0, 0, + 0, 0, ratio[2], 0, + 0, 0, 0, 1); M44f bradfordTrans = bradfordCPM * ratioMat * - inverseBradfordCPM; + inverseBradfordCPM; // // Build a combined file-RGB-to-ACES-RGB conversion matrix @@ -488,7 +489,7 @@ AcesInputFile::~AcesInputFile () } -void +void AcesInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride) { _data->rgbaFile->setFrameBuffer (base, xStride, yStride); @@ -498,7 +499,7 @@ AcesInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride) } -void +void AcesInputFile::readPixels (int scanLine1, int scanLine2) { // @@ -514,32 +515,32 @@ AcesInputFile::readPixels (int scanLine1, int scanLine2) // if (!_data->mustConvertColor) - return; + return; int minY = min (scanLine1, scanLine2); int maxY = max (scanLine1, scanLine2); for (int y = minY; y <= maxY; ++y) { - Rgba *base = _data->fbBase + - _data->fbXStride * _data->minX + - _data->fbYStride * y; + Rgba *base = _data->fbBase + + _data->fbXStride * _data->minX + + _data->fbYStride * y; - for (int x = _data->minX; x <= _data->maxX; ++x) - { - V3f aces = V3f (base->r, base->g, base->b) * _data->fileToAces; + for (int x = _data->minX; x <= _data->maxX; ++x) + { + V3f aces = V3f (base->r, base->g, base->b) * _data->fileToAces; - base->r = aces[0]; - base->g = aces[1]; - base->b = aces[2]; + base->r = aces[0]; + base->g = aces[1]; + base->b = aces[2]; - base += _data->fbXStride; - } + base += _data->fbXStride; + } } } -void +void AcesInputFile::readPixels (int scanLine) { readPixels (scanLine, scanLine); @@ -553,14 +554,14 @@ AcesInputFile::header () const } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & AcesInputFile::displayWindow () const { return _data->rgbaFile->displayWindow(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & AcesInputFile::dataWindow () const { return _data->rgbaFile->dataWindow(); @@ -574,7 +575,7 @@ AcesInputFile::pixelAspectRatio () const } -const Imath::V2f +const IMATH_NAMESPACE::V2f AcesInputFile::screenWindowCenter () const { return _data->rgbaFile->screenWindowCenter(); @@ -609,7 +610,7 @@ AcesInputFile::channels () const } -const char * +const char * AcesInputFile::fileName () const { return _data->rgbaFile->fileName(); @@ -629,4 +630,4 @@ AcesInputFile::version () const return _data->rgbaFile->version(); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfAcesFile.h b/3rdparty/openexr/IlmImf/ImfAcesFile.h index 36f95226d4..f8e9323598 100644 --- a/3rdparty/openexr/IlmImf/ImfAcesFile.h +++ b/3rdparty/openexr/IlmImf/ImfAcesFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2007, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,33 +41,33 @@ //----------------------------------------------------------------------------- // // ACES image file I/O. -// +// // This header file declares two classes that directly support // image file input and output according to the Academy Image // Interchange Framework. -// +// // The Academy Image Interchange file format is a subset of OpenEXR: -// +// // - Images are stored as scanlines. Tiles are not allowed. -// +// // - Images contain three color channels, either // R, G, B (red, green, blue) or // Y, RY, BY (luminance, sub-sampled chroma) -// +// // - Images may optionally contain an alpha channel. -// +// // - Only three compression types are allowed: // - NO_COMPRESSION (file is not compressed) // - PIZ_COMPRESSION (lossless) // - B44A_COMPRESSION (lossy) -// +// // - The "chromaticities" header attribute must specify // the ACES RGB primaries and white point. -// +// // class AcesOutputFile writes an OpenEXR file, enforcing the // restrictions listed above. Pixel data supplied by application // software must already be in the ACES RGB space. -// +// // class AcesInputFile reads an OpenEXR file. Pixel data delivered // to application software is guaranteed to be in the ACES RGB space. // If the RGB space of the file is not the same as the ACES space, @@ -77,20 +77,19 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfHeader.h" +#include "ImfRgba.h" #include "ImathVec.h" #include "ImathBox.h" -#include -#include +#include "ImfThreading.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" -namespace Imf { +#include +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -class RgbaOutputFile; -class RgbaInputFile; -struct PreviewRgba; -struct Chromaticities; // // ACES red, green, blue and white-point chromaticities. @@ -111,9 +110,10 @@ class AcesOutputFile // Constructor -- header is constructed by the caller //--------------------------------------------------- + IMF_EXPORT AcesOutputFile (const std::string &name, - const Header &header, - RgbaChannels rgbaChannels = WRITE_RGBA, + const Header &header, + RgbaChannels rgbaChannels = WRITE_RGBA, int numThreads = globalThreadCount()); @@ -123,9 +123,10 @@ class AcesOutputFile // automatically close the file. //---------------------------------------------------- - AcesOutputFile (OStream &os, - const Header &header, - RgbaChannels rgbaChannels = WRITE_RGBA, + IMF_EXPORT + AcesOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + RgbaChannels rgbaChannels = WRITE_RGBA, int numThreads = globalThreadCount()); @@ -134,15 +135,16 @@ class AcesOutputFile // call arguments (empty dataWindow means "same as displayWindow") //---------------------------------------------------------------- + IMF_EXPORT AcesOutputFile (const std::string &name, - const Imath::Box2i &displayWindow, - const Imath::Box2i &dataWindow = Imath::Box2i(), - RgbaChannels rgbaChannels = WRITE_RGBA, - float pixelAspectRatio = 1, - const Imath::V2f screenWindowCenter = Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression compression = PIZ_COMPRESSION, + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow = IMATH_NAMESPACE::Box2i(), + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = PIZ_COMPRESSION, int numThreads = globalThreadCount()); @@ -152,15 +154,16 @@ class AcesOutputFile // Box2i (V2i (0, 0), V2i (width - 1, height -1)) //----------------------------------------------- + IMF_EXPORT AcesOutputFile (const std::string &name, - int width, - int height, - RgbaChannels rgbaChannels = WRITE_RGBA, - float pixelAspectRatio = 1, - const Imath::V2f screenWindowCenter = Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression compression = PIZ_COMPRESSION, + int width, + int height, + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = PIZ_COMPRESSION, int numThreads = globalThreadCount()); @@ -168,6 +171,7 @@ class AcesOutputFile // Destructor //----------- + IMF_EXPORT virtual ~AcesOutputFile (); @@ -179,9 +183,10 @@ class AcesOutputFile // //------------------------------------------------ + IMF_EXPORT void setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride); + size_t xStride, + size_t yStride); //------------------------------------------------- @@ -197,14 +202,23 @@ class AcesOutputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; - const Imath::Box2i & displayWindow () const; - const Imath::Box2i & dataWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & displayWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & dataWindow () const; + IMF_EXPORT float pixelAspectRatio () const; - const Imath::V2f screenWindowCenter () const; + IMF_EXPORT + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + IMF_EXPORT float screenWindowWidth () const; + IMF_EXPORT LineOrder lineOrder () const; + IMF_EXPORT Compression compression () const; + IMF_EXPORT RgbaChannels channels () const; @@ -212,6 +226,7 @@ class AcesOutputFile // Update the preview image (see Imf::OutputFile::updatePreviewImage()) // -------------------------------------------------------------------- + IMF_EXPORT void updatePreviewImage (const PreviewRgba[]); @@ -239,8 +254,9 @@ class AcesInputFile // destructor will automatically close the file. //------------------------------------------------------- + IMF_EXPORT AcesInputFile (const std::string &name, - int numThreads = globalThreadCount()); + int numThreads = globalThreadCount()); //----------------------------------------------------------- @@ -250,14 +266,16 @@ class AcesInputFile // close the file. //----------------------------------------------------------- - AcesInputFile (IStream &is, - int numThreads = globalThreadCount()); + IMF_EXPORT + AcesInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int numThreads = globalThreadCount()); //----------- // Destructor //----------- + IMF_EXPORT virtual ~AcesInputFile (); @@ -269,9 +287,10 @@ class AcesInputFile // //----------------------------------------------------- + IMF_EXPORT void setFrameBuffer (Rgba *base, - size_t xStride, - size_t yStride); + size_t xStride, + size_t yStride); //-------------------------------------------- @@ -279,7 +298,9 @@ class AcesInputFile // Pixels returned will contain ACES RGB data. //-------------------------------------------- + IMF_EXPORT void readPixels (int scanLine1, int scanLine2); + IMF_EXPORT void readPixels (int scanLine); @@ -287,16 +308,27 @@ class AcesInputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; - const Imath::Box2i & displayWindow () const; - const Imath::Box2i & dataWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & displayWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & dataWindow () const; + IMF_EXPORT float pixelAspectRatio () const; - const Imath::V2f screenWindowCenter () const; + IMF_EXPORT + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + IMF_EXPORT float screenWindowWidth () const; + IMF_EXPORT LineOrder lineOrder () const; + IMF_EXPORT Compression compression () const; + IMF_EXPORT RgbaChannels channels () const; + IMF_EXPORT const char * fileName () const; + IMF_EXPORT bool isComplete () const; @@ -304,6 +336,7 @@ class AcesInputFile // Access to the file format version //---------------------------------- + IMF_EXPORT int version () const; private: @@ -317,6 +350,9 @@ class AcesInputFile }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfArray.h b/3rdparty/openexr/IlmImf/ImfArray.h index c86f871bd7..6a80d8fbad 100644 --- a/3rdparty/openexr/IlmImf/ImfArray.h +++ b/3rdparty/openexr/IlmImf/ImfArray.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -37,6 +37,8 @@ #ifndef INCLUDED_IMF_ARRAY_H #define INCLUDED_IMF_ARRAY_H +#include "ImfForward.h" + //------------------------------------------------------------------------- // // class Array @@ -53,24 +55,23 @@ // C () {std::cout << "C::C (" << this << ")\n";}; // virtual ~C () {std::cout << "C::~C (" << this << ")\n";}; // }; -// +// // int // main () // { // Array a(3); -// +// // C &b = a[1]; // const C &c = a[1]; // C *d = a + 2; // const C *e = a; -// +// // return 0; // } // //------------------------------------------------------------------------- -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER template class Array @@ -81,8 +82,8 @@ class Array // Constructors and destructors //----------------------------- - Array () {_data = 0;} - Array (long size) {_data = new T[size];} + Array () {_data = 0; _size = 0;} + Array (long size) {_data = new T[size]; _size = size;} ~Array () {delete [] _data;} @@ -110,11 +111,19 @@ class Array void resizeEraseUnsafe (long size); + //------------------------------- + // Return the size of this array. + //------------------------------- + + long size() const {return _size;} + + private: Array (const Array &); // Copying and assignment Array & operator = (const Array &); // are not implemented + long _size; T * _data; }; @@ -157,11 +166,20 @@ class Array2D void resizeEraseUnsafe (long sizeX, long sizeY); + //------------------------------- + // Return the size of this array. + //------------------------------- + + long height() const {return _sizeX;} + long width() const {return _sizeY;} + + private: Array2D (const Array2D &); // Copying and assignment Array2D & operator = (const Array2D &); // are not implemented + long _sizeX; long _sizeY; T * _data; }; @@ -177,6 +195,7 @@ Array::resizeErase (long size) { T *tmp = new T[size]; delete [] _data; + _size = size; _data = tmp; } @@ -187,14 +206,16 @@ Array::resizeEraseUnsafe (long size) { delete [] _data; _data = 0; + _size = 0; _data = new T[size]; + _size = size; } template inline Array2D::Array2D (): - _sizeY (0), _data (0) + _sizeX(0), _sizeY (0), _data (0) { // emtpy } @@ -203,7 +224,7 @@ Array2D::Array2D (): template inline Array2D::Array2D (long sizeX, long sizeY): - _sizeY (sizeY), _data (new T[sizeX * sizeY]) + _sizeX (sizeX), _sizeY (sizeY), _data (new T[sizeX * sizeY]) { // emtpy } @@ -218,7 +239,7 @@ Array2D::~Array2D () template -inline T * +inline T * Array2D::operator [] (long x) { return _data + x * _sizeY; @@ -239,6 +260,7 @@ Array2D::resizeErase (long sizeX, long sizeY) { T *tmp = new T[sizeX * sizeY]; delete [] _data; + _sizeX = sizeX; _sizeY = sizeY; _data = tmp; } @@ -250,12 +272,14 @@ Array2D::resizeEraseUnsafe (long sizeX, long sizeY) { delete [] _data; _data = 0; + _sizeX = 0; _sizeY = 0; _data = new T[sizeX * sizeY]; + _sizeX = sizeX; _sizeY = sizeY; } +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imf #endif diff --git a/3rdparty/openexr/IlmImf/ImfAttribute.cpp b/3rdparty/openexr/IlmImf/ImfAttribute.cpp index 0d6644e66d..7ac146e015 100644 --- a/3rdparty/openexr/IlmImf/ImfAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,11 +46,13 @@ #include #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -using IlmThread::Mutex; -using IlmThread::Lock; + +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; Attribute::Attribute () {} @@ -66,7 +68,7 @@ struct NameCompare: std::binary_function bool operator () (const char *x, const char *y) const { - return strcmp (x, y) < 0; + return strcmp (x, y) < 0; } }; @@ -86,22 +88,28 @@ class LockedTypeMap: public TypeMap LockedTypeMap & typeMap () { + // c++11 requires thread-safe static variable initialization +#if __cplusplus >= 201103L + static LockedTypeMap tMap; + return tMap; +#else static Mutex criticalSection; Lock lock (criticalSection); static LockedTypeMap* typeMap = 0; if (typeMap == 0) - typeMap = new LockedTypeMap (); + typeMap = new LockedTypeMap (); return *typeMap; +#endif } } // namespace -bool +bool Attribute::knownType (const char typeName[]) { LockedTypeMap& tMap = typeMap(); @@ -111,17 +119,17 @@ Attribute::knownType (const char typeName[]) } -void +void Attribute::registerAttributeType (const char typeName[], - Attribute *(*newAttribute)()) + Attribute *(*newAttribute)()) { LockedTypeMap& tMap = typeMap(); Lock lock (tMap.mutex); if (tMap.find (typeName) != tMap.end()) - THROW (Iex::ArgExc, "Cannot register image file attribute " - "type \"" << typeName << "\". " - "The type has already been registered."); + THROW (IEX_NAMESPACE::ArgExc, "Cannot register image file attribute " + "type \"" << typeName << "\". " + "The type has already been registered."); tMap.insert (TypeMap::value_type (typeName, newAttribute)); } @@ -146,11 +154,11 @@ Attribute::newAttribute (const char typeName[]) TypeMap::const_iterator i = tMap.find (typeName); if (i == tMap.end()) - THROW (Iex::ArgExc, "Cannot create image file attribute of " - "unknown type \"" << typeName << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "Cannot create image file attribute of " + "unknown type \"" << typeName << "\"."); return (i->second)(); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfAttribute.h b/3rdparty/openexr/IlmImf/ImfAttribute.h index 025609cf76..b39ce788c8 100644 --- a/3rdparty/openexr/IlmImf/ImfAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,11 +44,13 @@ //----------------------------------------------------------------------------- #include "IexBaseExc.h" -#include -#include - +#include "ImfIO.h" +#include "ImfXdr.h" +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class Attribute @@ -59,7 +61,9 @@ class Attribute // Constructor and destructor //--------------------------- + IMF_EXPORT Attribute (); + IMF_EXPORT virtual ~Attribute (); @@ -81,12 +85,12 @@ class Attribute // Type-specific attribute I/O and copying //---------------------------------------- - virtual void writeValueTo (OStream &os, - int version) const = 0; + virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + int version) const = 0; - virtual void readValueFrom (IStream &is, - int size, - int version) = 0; + virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version) = 0; virtual void copyValueFrom (const Attribute &other) = 0; @@ -95,6 +99,7 @@ class Attribute // Attribute factory //------------------ + IMF_EXPORT static Attribute * newAttribute (const char typeName[]); @@ -102,6 +107,7 @@ class Attribute // Test if a given attribute type has already been registered //----------------------------------------------------------- + IMF_EXPORT static bool knownType (const char typeName[]); @@ -112,8 +118,9 @@ class Attribute // knows how to make objects of this type. //-------------------------------------------------- + IMF_EXPORT static void registerAttributeType (const char typeName[], - Attribute *(*newAttribute)()); + Attribute *(*newAttribute)()); //------------------------------------------------------ // Un-register an attribute type so that newAttribute() @@ -121,6 +128,7 @@ class Attribute // debugging only). //------------------------------------------------------ + IMF_EXPORT static void unRegisterAttributeType (const char typeName[]); }; @@ -128,7 +136,7 @@ class Attribute //------------------------------------------------- // Class template for attributes of a specific type //------------------------------------------------- - + template class TypedAttribute: public Attribute { @@ -157,7 +165,7 @@ class TypedAttribute: public Attribute //-------------------------------- virtual const char * typeName () const; - + //--------------------------------------------------------- // Static version of typeName() @@ -165,7 +173,7 @@ class TypedAttribute: public Attribute //--------------------------------------------------------- static const char * staticTypeName (); - + //--------------------- // Make a new attribute @@ -186,12 +194,12 @@ class TypedAttribute: public Attribute // Depending on type T, these functions may have to be specialized. //----------------------------------------------------------------- - virtual void writeValueTo (OStream &os, - int version) const; + virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + int version) const; - virtual void readValueFrom (IStream &is, - int size, - int version); + virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version); virtual void copyValueFrom (const Attribute &other); @@ -233,11 +241,9 @@ class TypedAttribute: public Attribute T _value; }; - //------------------------------------ // Implementation of TypedAttribute //------------------------------------ - template TypedAttribute::TypedAttribute (): Attribute (), @@ -248,7 +254,7 @@ TypedAttribute::TypedAttribute (): template -TypedAttribute::TypedAttribute (const T &value): +TypedAttribute::TypedAttribute (const T & value): Attribute (), _value (value) { @@ -289,7 +295,7 @@ TypedAttribute::value () const template -const char * +const char * TypedAttribute::typeName () const { return staticTypeName(); @@ -315,23 +321,26 @@ TypedAttribute::copy () const template -void -TypedAttribute::writeValueTo (OStream &os, int) const +void +TypedAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + int version) const { - Xdr::write (os, _value); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, _value); } template -void -TypedAttribute::readValueFrom (IStream &is, int, int) +void +TypedAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version) { - Xdr::read (is, _value); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, _value); } template -void +void TypedAttribute::copyValueFrom (const Attribute &other) { _value = cast(other)._value; @@ -343,10 +352,10 @@ TypedAttribute * TypedAttribute::cast (Attribute *attribute) { TypedAttribute *t = - dynamic_cast *> (attribute); + dynamic_cast *> (attribute); if (t == 0) - throw Iex::TypeExc ("Unexpected attribute type."); + throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); return t; } @@ -357,10 +366,10 @@ const TypedAttribute * TypedAttribute::cast (const Attribute *attribute) { const TypedAttribute *t = - dynamic_cast *> (attribute); + dynamic_cast *> (attribute); if (t == 0) - throw Iex::TypeExc ("Unexpected attribute type."); + throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); return t; } @@ -398,30 +407,7 @@ TypedAttribute::unRegisterAttributeType () } -} // namespace Imf - -#if defined(OPENEXR_DLL) && defined(_MSC_VER) - // Tell MS VC++ to disable "non dll-interface class used as base - // for dll-interface class" and "no suitable definition provided - // for explicit template" - #pragma warning (disable : 4275 4661) - - #if defined (ILMIMF_EXPORTS) - #define IMF_EXPIMP_TEMPLATE - #else - #define IMF_EXPIMP_TEMPLATE extern - #endif - - IMF_EXPIMP_TEMPLATE template class Imf::TypedAttribute; - IMF_EXPIMP_TEMPLATE template class Imf::TypedAttribute; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT - #pragma warning(default : 4251) - #undef EXTERN_TEMPLATE -#endif - -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif #endif diff --git a/3rdparty/openexr/IlmImf/ImfAutoArray.h b/3rdparty/openexr/IlmImf/ImfAutoArray.h index 37320aa459..c1ecaff14c 100644 --- a/3rdparty/openexr/IlmImf/ImfAutoArray.h +++ b/3rdparty/openexr/IlmImf/ImfAutoArray.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,13 +44,10 @@ // //----------------------------------------------------------------------------- -#include "OpenEXRConfig.h" - -#if !defined (HAVE_LARGE_STACK) +#include "ImfNamespace.h" #include -#endif -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER #if !defined (HAVE_LARGE_STACK) @@ -61,15 +58,15 @@ namespace Imf { { public: - AutoArray (): _data (new T [size]) { memset(_data, 0, size*sizeof(T)); } - ~AutoArray () {delete [] _data;} - - operator T * () {return _data;} - operator const T * () const {return _data;} + AutoArray (): _data (new T [size]) { memset(_data, 0, size*sizeof(T)); } + ~AutoArray () {delete [] _data;} + operator T * () {return _data;} + operator const T * () const {return _data;} + private: - T *_data; + T *_data; }; @@ -81,17 +78,18 @@ namespace Imf { { public: - operator T * () {return _data;} - operator const T * () const {return _data;} - + operator T * () {return _data;} + operator const T * () const {return _data;} + private: - T _data[size]; + T _data[size]; }; #endif -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + #endif diff --git a/3rdparty/openexr/IlmImf/ImfB44Compressor.cpp b/3rdparty/openexr/IlmImf/ImfB44Compressor.cpp index 1a2be806d9..f13e143f52 100644 --- a/3rdparty/openexr/IlmImf/ImfB44Compressor.cpp +++ b/3rdparty/openexr/IlmImf/ImfB44Compressor.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -63,7 +63,7 @@ // | // | 0 // | -// v +// v // 4 --------> 5 --------> 6 --------> 7 // | 4 8 12 // | @@ -97,11 +97,11 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include +#include "ImfB44Compressor.h" +#include "ImfHeader.h" +#include "ImfChannelList.h" +#include "ImfMisc.h" +#include "ImfCheckedArithmetic.h" #include #include #include @@ -110,13 +110,16 @@ #include #include #include +#include "ImfNamespace.h" + -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -using Imath::divp; -using Imath::modp; -using Imath::Box2i; -using Imath::V2i; + +using IMATH_NAMESPACE::divp; +using IMATH_NAMESPACE::modp; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::V2i; using std::min; namespace { @@ -124,7 +127,7 @@ namespace { // // Lookup tables for // y = exp (x / 8) -// and +// and // x = 8 * log (y) // @@ -135,7 +138,7 @@ inline void convertFromLinear (unsigned short s[16]) { for (int i = 0; i < 16; ++i) - s[i] = expTable[s[i]]; + s[i] = expTable[s[i]]; } @@ -143,7 +146,7 @@ inline void convertToLinear (unsigned short s[16]) { for (int i = 0; i < 16; ++i) - s[i] = logTable[s[i]]; + s[i] = logTable[s[i]]; } @@ -225,14 +228,14 @@ pack (const unsigned short s[16], for (int i = 0; i < 16; ++i) { - if ((s[i] & 0x7c00) == 0x7c00) - t[i] = 0x8000; - else if (s[i] & 0x8000) - t[i] = ~s[i]; - else - t[i] = s[i] | 0x8000; + if ((s[i] & 0x7c00) == 0x7c00) + t[i] = 0x8000; + else if (s[i] & 0x8000) + t[i] = ~s[i]; + else + t[i] = s[i] | 0x8000; } - + // // Find the maximum, tMax, of t[0] ... t[15]. // @@ -240,8 +243,8 @@ pack (const unsigned short s[16], unsigned short tMax = 0; for (int i = 0; i < 16; ++i) - if (tMax < t[i]) - tMax = t[i]; + if (tMax < t[i]) + tMax = t[i]; // // Compute a set of running differences, r[0] ... r[14]: @@ -261,79 +264,79 @@ pack (const unsigned short s[16], do { - shift += 1; + shift += 1; - // - // Compute absolute differences, d[0] ... d[15], - // between tMax and t[0] ... t[15]. - // - // Shift and round the absolute differences. - // + // + // Compute absolute differences, d[0] ... d[15], + // between tMax and t[0] ... t[15]. + // + // Shift and round the absolute differences. + // - for (int i = 0; i < 16; ++i) - d[i] = shiftAndRound (tMax - t[i], shift); + for (int i = 0; i < 16; ++i) + d[i] = shiftAndRound (tMax - t[i], shift); - // - // Convert d[0] .. d[15] into running differences - // + // + // Convert d[0] .. d[15] into running differences + // - r[ 0] = d[ 0] - d[ 4] + bias; - r[ 1] = d[ 4] - d[ 8] + bias; - r[ 2] = d[ 8] - d[12] + bias; + r[ 0] = d[ 0] - d[ 4] + bias; + r[ 1] = d[ 4] - d[ 8] + bias; + r[ 2] = d[ 8] - d[12] + bias; - r[ 3] = d[ 0] - d[ 1] + bias; - r[ 4] = d[ 4] - d[ 5] + bias; - r[ 5] = d[ 8] - d[ 9] + bias; - r[ 6] = d[12] - d[13] + bias; + r[ 3] = d[ 0] - d[ 1] + bias; + r[ 4] = d[ 4] - d[ 5] + bias; + r[ 5] = d[ 8] - d[ 9] + bias; + r[ 6] = d[12] - d[13] + bias; - r[ 7] = d[ 1] - d[ 2] + bias; - r[ 8] = d[ 5] - d[ 6] + bias; - r[ 9] = d[ 9] - d[10] + bias; - r[10] = d[13] - d[14] + bias; + r[ 7] = d[ 1] - d[ 2] + bias; + r[ 8] = d[ 5] - d[ 6] + bias; + r[ 9] = d[ 9] - d[10] + bias; + r[10] = d[13] - d[14] + bias; - r[11] = d[ 2] - d[ 3] + bias; - r[12] = d[ 6] - d[ 7] + bias; - r[13] = d[10] - d[11] + bias; - r[14] = d[14] - d[15] + bias; + r[11] = d[ 2] - d[ 3] + bias; + r[12] = d[ 6] - d[ 7] + bias; + r[13] = d[10] - d[11] + bias; + r[14] = d[14] - d[15] + bias; - rMin = r[0]; - rMax = r[0]; + rMin = r[0]; + rMax = r[0]; - for (int i = 1; i < 15; ++i) - { - if (rMin > r[i]) - rMin = r[i]; + for (int i = 1; i < 15; ++i) + { + if (rMin > r[i]) + rMin = r[i]; - if (rMax < r[i]) - rMax = r[i]; - } + if (rMax < r[i]) + rMax = r[i]; + } } while (rMin < 0 || rMax > 0x3f); if (rMin == bias && rMax == bias && optFlatFields) { - // - // Special case - all pixels have the same value. - // We encode this in 3 instead of 14 bytes by - // storing the value 0xfc in the third output byte, - // which cannot occur in the 14-byte encoding. - // + // + // Special case - all pixels have the same value. + // We encode this in 3 instead of 14 bytes by + // storing the value 0xfc in the third output byte, + // which cannot occur in the 14-byte encoding. + // - b[0] = (t[0] >> 8); - b[1] = t[0]; - b[2] = 0xfc; + b[0] = (t[0] >> 8); + b[1] = (unsigned char) t[0]; + b[2] = 0xfc; - return 3; + return 3; } if (exactMax) { - // - // Adjust t[0] so that the pixel whose value is equal - // to tMax gets represented as accurately as possible. - // + // + // Adjust t[0] so that the pixel whose value is equal + // to tMax gets represented as accurately as possible. + // - t[0] = tMax - (d[0] << shift); + t[0] = tMax - (d[0] << shift); } // @@ -341,7 +344,7 @@ pack (const unsigned short s[16], // b[ 0] = (t[0] >> 8); - b[ 1] = t[0]; + b[ 1] = (unsigned char) t[0]; b[ 2] = (unsigned char) ((shift << 2) | (r[ 0] >> 4)); b[ 3] = (unsigned char) ((r[ 0] << 4) | (r[ 1] >> 2)); @@ -372,7 +375,7 @@ unpack14 (const unsigned char b[14], unsigned short s[16]) // #if defined (DEBUG) - assert (b[2] != 0xfc); + assert (b[2] != 0xfc); #endif s[ 0] = (b[0] << 8) | b[1]; @@ -383,17 +386,17 @@ unpack14 (const unsigned char b[14], unsigned short s[16]) s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias; s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias; s[12] = s[ 8] + ((b[ 4] & 0x3f) << shift) - bias; - + s[ 1] = s[ 0] + ((b[ 5] >> 2) << shift) - bias; s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias; s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias; s[13] = s[12] + ((b[ 7] & 0x3f) << shift) - bias; - + s[ 2] = s[ 1] + ((b[ 8] >> 2) << shift) - bias; s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias; s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias; s[14] = s[13] + ((b[10] & 0x3f) << shift) - bias; - + s[ 3] = s[ 2] + ((b[11] >> 2) << shift) - bias; s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias; s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias; @@ -401,10 +404,10 @@ unpack14 (const unsigned char b[14], unsigned short s[16]) for (int i = 0; i < 16; ++i) { - if (s[i] & 0x8000) - s[i] &= 0x7fff; - else - s[i] = ~s[i]; + if (s[i] & 0x8000) + s[i] &= 0x7fff; + else + s[i] = ~s[i]; } } @@ -418,34 +421,34 @@ unpack3 (const unsigned char b[3], unsigned short s[16]) // #if defined (DEBUG) - assert (b[2] == 0xfc); + assert (b[2] == 0xfc); #endif s[0] = (b[0] << 8) | b[1]; if (s[0] & 0x8000) - s[0] &= 0x7fff; + s[0] &= 0x7fff; else - s[0] = ~s[0]; + s[0] = ~s[0]; for (int i = 1; i < 16; ++i) - s[i] = s[0]; + s[i] = s[0]; } void notEnoughData () { - throw Iex::InputExc ("Error decompressing data " - "(input data are shorter than expected)."); + throw IEX_NAMESPACE::InputExc ("Error decompressing data " + "(input data are shorter than expected)."); } void tooMuchData () { - throw Iex::InputExc ("Error decompressing data " - "(input data are longer than expected)."); + throw IEX_NAMESPACE::InputExc ("Error decompressing data " + "(input data are longer than expected)."); } } // namespace @@ -496,14 +499,14 @@ B44Compressor::B44Compressor int numHalfChans = 0; for (ChannelList::ConstIterator c = channels.begin(); - c != channels.end(); - ++c) + c != channels.end(); + ++c) { - assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0); - ++_numChans; + assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0); + ++_numChans; - if (c.channel().type == HALF) - ++numHalfChans; + if (c.channel().type == HALF) + ++numHalfChans; } // @@ -520,14 +523,14 @@ B44Compressor::B44Compressor int i = 0; for (ChannelList::ConstIterator c = channels.begin(); - c != channels.end(); - ++c, ++i) + c != channels.end(); + ++c, ++i) { - _channelData[i].ys = c.channel().ySampling; - _channelData[i].type = c.channel().type; - _channelData[i].pLinear = c.channel().pLinear; - _channelData[i].size = - pixelTypeSize (c.channel().type) / pixelTypeSize (HALF); + _channelData[i].ys = c.channel().ySampling; + _channelData[i].type = c.channel().type; + _channelData[i].pLinear = c.channel().pLinear; + _channelData[i].size = + pixelTypeSize (c.channel().type) / pixelTypeSize (HALF); } const Box2i &dataWindow = hdr.dataWindow(); @@ -544,7 +547,7 @@ B44Compressor::B44Compressor assert (sizeof (unsigned short) == pixelTypeSize (HALF)); if (_numChans == numHalfChans) - _format = NATIVE; + _format = NATIVE; } @@ -572,23 +575,23 @@ B44Compressor::format () const int B44Compressor::compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { return compress (inPtr, - inSize, - Box2i (V2i (_minX, minY), - V2i (_maxX, minY + numScanLines() - 1)), - outPtr); + inSize, + Box2i (V2i (_minX, minY), + V2i (_maxX, minY + numScanLines() - 1)), + outPtr); } int B44Compressor::compressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr) + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) { return compress (inPtr, inSize, range, outPtr); } @@ -596,23 +599,23 @@ B44Compressor::compressTile (const char *inPtr, int B44Compressor::uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { return uncompress (inPtr, - inSize, - Box2i (V2i (_minX, minY), - V2i (_maxX, minY + numScanLines() - 1)), - outPtr); + inSize, + Box2i (V2i (_minX, minY), + V2i (_maxX, minY + numScanLines() - 1)), + outPtr); } int B44Compressor::uncompressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr) + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) { return uncompress (inPtr, inSize, range, outPtr); } @@ -620,9 +623,9 @@ B44Compressor::uncompressTile (const char *inPtr, int B44Compressor::compress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr) + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) { // // Compress a block of pixel data: First copy the input pixels @@ -637,11 +640,11 @@ B44Compressor::compress (const char *inPtr, if (inSize == 0) { - // - // Special case - empty input buffer. - // + // + // Special case - empty input buffer. + // - return 0; + return 0; } // @@ -654,88 +657,88 @@ B44Compressor::compress (const char *inPtr, int maxX = min (range.max.x, _maxX); int minY = range.min.y; int maxY = min (range.max.y, _maxY); - + unsigned short *tmpBufferEnd = _tmpBuffer; int i = 0; for (ChannelList::ConstIterator c = _channels.begin(); - c != _channels.end(); - ++c, ++i) + c != _channels.end(); + ++c, ++i) { - ChannelData &cd = _channelData[i]; + ChannelData &cd = _channelData[i]; - cd.start = tmpBufferEnd; - cd.end = cd.start; + cd.start = tmpBufferEnd; + cd.end = cd.start; - cd.nx = numSamples (c.channel().xSampling, minX, maxX); - cd.ny = numSamples (c.channel().ySampling, minY, maxY); + cd.nx = numSamples (c.channel().xSampling, minX, maxX); + cd.ny = numSamples (c.channel().ySampling, minY, maxY); - tmpBufferEnd += cd.nx * cd.ny * cd.size; + tmpBufferEnd += cd.nx * cd.ny * cd.size; } if (_format == XDR) { - // - // The data in the input buffer are in the machine-independent - // Xdr format. Copy the HALF channels into _tmpBuffer and - // convert them back into native format for compression. - // Copy UINT and FLOAT channels verbatim into _tmpBuffer. - // - - for (int y = minY; y <= maxY; ++y) - { - for (int i = 0; i < _numChans; ++i) - { - ChannelData &cd = _channelData[i]; - - if (modp (y, cd.ys) != 0) - continue; - - if (cd.type == HALF) - { - for (int x = cd.nx; x > 0; --x) - { - Xdr::read (inPtr, *cd.end); - ++cd.end; - } - } - else - { - int n = cd.nx * cd.size; - memcpy (cd.end, inPtr, n * sizeof (unsigned short)); - inPtr += n * sizeof (unsigned short); - cd.end += n; - } - } - } + // + // The data in the input buffer are in the machine-independent + // Xdr format. Copy the HALF channels into _tmpBuffer and + // convert them back into native format for compression. + // Copy UINT and FLOAT channels verbatim into _tmpBuffer. + // + + for (int y = minY; y <= maxY; ++y) + { + for (int i = 0; i < _numChans; ++i) + { + ChannelData &cd = _channelData[i]; + + if (modp (y, cd.ys) != 0) + continue; + + if (cd.type == HALF) + { + for (int x = cd.nx; x > 0; --x) + { + Xdr::read (inPtr, *cd.end); + ++cd.end; + } + } + else + { + int n = cd.nx * cd.size; + memcpy (cd.end, inPtr, n * sizeof (unsigned short)); + inPtr += n * sizeof (unsigned short); + cd.end += n; + } + } + } } else { - // - // The input buffer contains only HALF channels, and they - // are in native, machine-dependent format. Copy the pixels - // into _tmpBuffer. - // - - for (int y = minY; y <= maxY; ++y) - { - for (int i = 0; i < _numChans; ++i) - { - ChannelData &cd = _channelData[i]; - - #if defined (DEBUG) - assert (cd.type == HALF); - #endif - - if (modp (y, cd.ys) != 0) - continue; - - int n = cd.nx * cd.size; - memcpy (cd.end, inPtr, n * sizeof (unsigned short)); - inPtr += n * sizeof (unsigned short); - cd.end += n; - } - } + // + // The input buffer contains only HALF channels, and they + // are in native, machine-dependent format. Copy the pixels + // into _tmpBuffer. + // + + for (int y = minY; y <= maxY; ++y) + { + for (int i = 0; i < _numChans; ++i) + { + ChannelData &cd = _channelData[i]; + + #if defined (DEBUG) + assert (cd.type == HALF); + #endif + + if (modp (y, cd.ys) != 0) + continue; + + int n = cd.nx * cd.size; + memcpy (cd.end, inPtr, n * sizeof (unsigned short)); + inPtr += n * sizeof (unsigned short); + cd.end += n; + } + } } // @@ -746,10 +749,10 @@ B44Compressor::compress (const char *inPtr, #if defined (DEBUG) - for (int i = 1; i < _numChans; ++i) - assert (_channelData[i-1].end == _channelData[i].start); + for (int i = 1; i < _numChans; ++i) + assert (_channelData[i-1].end == _channelData[i].start); - assert (_channelData[_numChans-1].end == tmpBufferEnd); + assert (_channelData[_numChans-1].end == tmpBufferEnd); #endif @@ -766,94 +769,94 @@ B44Compressor::compress (const char *inPtr, for (int i = 0; i < _numChans; ++i) { - ChannelData &cd = _channelData[i]; - - if (cd.type != HALF) - { - // - // UINT or FLOAT channel. - // - - int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short); - memcpy (outEnd, cd.start, n); - outEnd += n; - - continue; - } - - // - // HALF channel - // - - for (int y = 0; y < cd.ny; y += 4) - { - // - // Copy the next 4x4 pixel block into array s. - // If the width, cd.nx, or the height, cd.ny, of - // the pixel data in _tmpBuffer is not divisible - // by 4, then pad the data by repeating the - // rightmost column and the bottom row. - // - - unsigned short *row0 = cd.start + y * cd.nx; - unsigned short *row1 = row0 + cd.nx; - unsigned short *row2 = row1 + cd.nx; - unsigned short *row3 = row2 + cd.nx; - - if (y + 3 >= cd.ny) - { - if (y + 1 >= cd.ny) - row1 = row0; - - if (y + 2 >= cd.ny) - row2 = row1; - - row3 = row2; - } - - for (int x = 0; x < cd.nx; x += 4) - { - unsigned short s[16]; - - if (x + 3 >= cd.nx) - { - int n = cd.nx - x; - - for (int i = 0; i < 4; ++i) - { - int j = min (i, n - 1); - - s[i + 0] = row0[j]; - s[i + 4] = row1[j]; - s[i + 8] = row2[j]; - s[i + 12] = row3[j]; - } - } - else - { - memcpy (&s[ 0], row0, 4 * sizeof (unsigned short)); - memcpy (&s[ 4], row1, 4 * sizeof (unsigned short)); - memcpy (&s[ 8], row2, 4 * sizeof (unsigned short)); - memcpy (&s[12], row3, 4 * sizeof (unsigned short)); - } - - row0 += 4; - row1 += 4; - row2 += 4; - row3 += 4; - - // - // Compress the contents of array s and append the - // results to the output buffer. - // - - if (cd.pLinear) - convertFromLinear (s); - - outEnd += pack (s, (unsigned char *) outEnd, - _optFlatFields, !cd.pLinear); - } - } + ChannelData &cd = _channelData[i]; + + if (cd.type != HALF) + { + // + // UINT or FLOAT channel. + // + + int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short); + memcpy (outEnd, cd.start, n); + outEnd += n; + + continue; + } + + // + // HALF channel + // + + for (int y = 0; y < cd.ny; y += 4) + { + // + // Copy the next 4x4 pixel block into array s. + // If the width, cd.nx, or the height, cd.ny, of + // the pixel data in _tmpBuffer is not divisible + // by 4, then pad the data by repeating the + // rightmost column and the bottom row. + // + + unsigned short *row0 = cd.start + y * cd.nx; + unsigned short *row1 = row0 + cd.nx; + unsigned short *row2 = row1 + cd.nx; + unsigned short *row3 = row2 + cd.nx; + + if (y + 3 >= cd.ny) + { + if (y + 1 >= cd.ny) + row1 = row0; + + if (y + 2 >= cd.ny) + row2 = row1; + + row3 = row2; + } + + for (int x = 0; x < cd.nx; x += 4) + { + unsigned short s[16]; + + if (x + 3 >= cd.nx) + { + int n = cd.nx - x; + + for (int i = 0; i < 4; ++i) + { + int j = min (i, n - 1); + + s[i + 0] = row0[j]; + s[i + 4] = row1[j]; + s[i + 8] = row2[j]; + s[i + 12] = row3[j]; + } + } + else + { + memcpy (&s[ 0], row0, 4 * sizeof (unsigned short)); + memcpy (&s[ 4], row1, 4 * sizeof (unsigned short)); + memcpy (&s[ 8], row2, 4 * sizeof (unsigned short)); + memcpy (&s[12], row3, 4 * sizeof (unsigned short)); + } + + row0 += 4; + row1 += 4; + row2 += 4; + row3 += 4; + + // + // Compress the contents of array s and append the + // results to the output buffer. + // + + if (cd.pLinear) + convertFromLinear (s); + + outEnd += pack (s, (unsigned char *) outEnd, + _optFlatFields, !cd.pLinear); + } + } } return outEnd - _outBuffer; @@ -862,9 +865,9 @@ B44Compressor::compress (const char *inPtr, int B44Compressor::uncompress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr) + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) { // // This function is the reverse of the compress() function, @@ -880,190 +883,190 @@ B44Compressor::uncompress (const char *inPtr, if (inSize == 0) { - return 0; + return 0; } int minX = range.min.x; int maxX = min (range.max.x, _maxX); int minY = range.min.y; int maxY = min (range.max.y, _maxY); - + unsigned short *tmpBufferEnd = _tmpBuffer; int i = 0; for (ChannelList::ConstIterator c = _channels.begin(); - c != _channels.end(); - ++c, ++i) + c != _channels.end(); + ++c, ++i) { - ChannelData &cd = _channelData[i]; + ChannelData &cd = _channelData[i]; - cd.start = tmpBufferEnd; - cd.end = cd.start; + cd.start = tmpBufferEnd; + cd.end = cd.start; - cd.nx = numSamples (c.channel().xSampling, minX, maxX); - cd.ny = numSamples (c.channel().ySampling, minY, maxY); + cd.nx = numSamples (c.channel().xSampling, minX, maxX); + cd.ny = numSamples (c.channel().ySampling, minY, maxY); - tmpBufferEnd += cd.nx * cd.ny * cd.size; + tmpBufferEnd += cd.nx * cd.ny * cd.size; } for (int i = 0; i < _numChans; ++i) { - ChannelData &cd = _channelData[i]; - - if (cd.type != HALF) - { - // - // UINT or FLOAT channel. - // - - int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short); - - if (inSize < n) - notEnoughData(); - - memcpy (cd.start, inPtr, n); - inPtr += n; - inSize -= n; - - continue; - } - - // - // HALF channel - // - - for (int y = 0; y < cd.ny; y += 4) - { - unsigned short *row0 = cd.start + y * cd.nx; - unsigned short *row1 = row0 + cd.nx; - unsigned short *row2 = row1 + cd.nx; - unsigned short *row3 = row2 + cd.nx; - - for (int x = 0; x < cd.nx; x += 4) - { - unsigned short s[16]; - - if (inSize < 3) - notEnoughData(); - - if (((const unsigned char *)inPtr)[2] == 0xfc) - { - unpack3 ((const unsigned char *)inPtr, s); - inPtr += 3; - inSize -= 3; - } - else - { - if (inSize < 14) - notEnoughData(); - - unpack14 ((const unsigned char *)inPtr, s); - inPtr += 14; - inSize -= 14; - } - - if (cd.pLinear) - convertToLinear (s); - - int n = (x + 3 < cd.nx)? - 4 * sizeof (unsigned short) : - (cd.nx - x) * sizeof (unsigned short); - - if (y + 3 < cd.ny) - { - memcpy (row0, &s[ 0], n); - memcpy (row1, &s[ 4], n); - memcpy (row2, &s[ 8], n); - memcpy (row3, &s[12], n); - } - else - { - memcpy (row0, &s[ 0], n); - - if (y + 1 < cd.ny) - memcpy (row1, &s[ 4], n); - - if (y + 2 < cd.ny) - memcpy (row2, &s[ 8], n); - } - - row0 += 4; - row1 += 4; - row2 += 4; - row3 += 4; - } - } + ChannelData &cd = _channelData[i]; + + if (cd.type != HALF) + { + // + // UINT or FLOAT channel. + // + + int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short); + + if (inSize < n) + notEnoughData(); + + memcpy (cd.start, inPtr, n); + inPtr += n; + inSize -= n; + + continue; + } + + // + // HALF channel + // + + for (int y = 0; y < cd.ny; y += 4) + { + unsigned short *row0 = cd.start + y * cd.nx; + unsigned short *row1 = row0 + cd.nx; + unsigned short *row2 = row1 + cd.nx; + unsigned short *row3 = row2 + cd.nx; + + for (int x = 0; x < cd.nx; x += 4) + { + unsigned short s[16]; + + if (inSize < 3) + notEnoughData(); + + if (((const unsigned char *)inPtr)[2] == 0xfc) + { + unpack3 ((const unsigned char *)inPtr, s); + inPtr += 3; + inSize -= 3; + } + else + { + if (inSize < 14) + notEnoughData(); + + unpack14 ((const unsigned char *)inPtr, s); + inPtr += 14; + inSize -= 14; + } + + if (cd.pLinear) + convertToLinear (s); + + int n = (x + 3 < cd.nx)? + 4 * sizeof (unsigned short) : + (cd.nx - x) * sizeof (unsigned short); + + if (y + 3 < cd.ny) + { + memcpy (row0, &s[ 0], n); + memcpy (row1, &s[ 4], n); + memcpy (row2, &s[ 8], n); + memcpy (row3, &s[12], n); + } + else + { + memcpy (row0, &s[ 0], n); + + if (y + 1 < cd.ny) + memcpy (row1, &s[ 4], n); + + if (y + 2 < cd.ny) + memcpy (row2, &s[ 8], n); + } + + row0 += 4; + row1 += 4; + row2 += 4; + row3 += 4; + } + } } char *outEnd = _outBuffer; if (_format == XDR) { - for (int y = minY; y <= maxY; ++y) - { - for (int i = 0; i < _numChans; ++i) - { - ChannelData &cd = _channelData[i]; - - if (modp (y, cd.ys) != 0) - continue; - - if (cd.type == HALF) - { - for (int x = cd.nx; x > 0; --x) - { - Xdr::write (outEnd, *cd.end); - ++cd.end; - } - } - else - { - int n = cd.nx * cd.size; - memcpy (outEnd, cd.end, n * sizeof (unsigned short)); - outEnd += n * sizeof (unsigned short); - cd.end += n; - } - } - } + for (int y = minY; y <= maxY; ++y) + { + for (int i = 0; i < _numChans; ++i) + { + ChannelData &cd = _channelData[i]; + + if (modp (y, cd.ys) != 0) + continue; + + if (cd.type == HALF) + { + for (int x = cd.nx; x > 0; --x) + { + Xdr::write (outEnd, *cd.end); + ++cd.end; + } + } + else + { + int n = cd.nx * cd.size; + memcpy (outEnd, cd.end, n * sizeof (unsigned short)); + outEnd += n * sizeof (unsigned short); + cd.end += n; + } + } + } } else { - for (int y = minY; y <= maxY; ++y) - { - for (int i = 0; i < _numChans; ++i) - { - ChannelData &cd = _channelData[i]; - - #if defined (DEBUG) - assert (cd.type == HALF); - #endif - - if (modp (y, cd.ys) != 0) - continue; - - int n = cd.nx * cd.size; - memcpy (outEnd, cd.end, n * sizeof (unsigned short)); - outEnd += n * sizeof (unsigned short); - cd.end += n; - } - } + for (int y = minY; y <= maxY; ++y) + { + for (int i = 0; i < _numChans; ++i) + { + ChannelData &cd = _channelData[i]; + + #if defined (DEBUG) + assert (cd.type == HALF); + #endif + + if (modp (y, cd.ys) != 0) + continue; + + int n = cd.nx * cd.size; + memcpy (outEnd, cd.end, n * sizeof (unsigned short)); + outEnd += n * sizeof (unsigned short); + cd.end += n; + } + } } #if defined (DEBUG) - for (int i = 1; i < _numChans; ++i) - assert (_channelData[i-1].end == _channelData[i].start); + for (int i = 1; i < _numChans; ++i) + assert (_channelData[i-1].end == _channelData[i].start); - assert (_channelData[_numChans-1].end == tmpBufferEnd); + assert (_channelData[_numChans-1].end == tmpBufferEnd); #endif if (inSize > 0) - tooMuchData(); + tooMuchData(); outPtr = _outBuffer; return outEnd - _outBuffer; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfB44Compressor.h b/3rdparty/openexr/IlmImf/ImfB44Compressor.h index 809eebe997..c84eaac40e 100644 --- a/3rdparty/openexr/IlmImf/ImfB44Compressor.h +++ b/3rdparty/openexr/IlmImf/ImfB44Compressor.h @@ -2,9 +2,9 @@ // // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,60 +42,69 @@ // //----------------------------------------------------------------------------- -#include - -namespace Imf { +#include "ImfCompressor.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" -class ChannelList; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class B44Compressor: public Compressor { public: + IMF_EXPORT B44Compressor (const Header &hdr, size_t maxScanLineSize, - size_t numScanLines, - bool optFlatFields); + size_t numScanLines, + bool optFlatFields); + IMF_EXPORT virtual ~B44Compressor (); + IMF_EXPORT virtual int numScanLines () const; + IMF_EXPORT virtual Format format () const; + IMF_EXPORT virtual int compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); - + int inSize, + int minY, + const char *&outPtr); + + IMF_EXPORT virtual int compressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + IMF_EXPORT virtual int uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); - + int inSize, + int minY, + const char *&outPtr); + + IMF_EXPORT virtual int uncompressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); private: struct ChannelData; - + int compress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); - + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + int uncompress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); int _maxScanLineSize; bool _optFlatFields; @@ -112,6 +121,6 @@ class B44Compressor: public Compressor }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfBoxAttribute.cpp b/3rdparty/openexr/IlmImf/ImfBoxAttribute.cpp index fa839ee804..6d44d0c34d 100644 --- a/3rdparty/openexr/IlmImf/ImfBoxAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfBoxAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,8 +44,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -57,7 +58,7 @@ Box2iAttribute::staticTypeName () template <> void -Box2iAttribute::writeValueTo (OStream &os, int) const +Box2iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.min.x); Xdr::write (os, _value.min.y); @@ -68,7 +69,7 @@ Box2iAttribute::writeValueTo (OStream &os, int) const template <> void -Box2iAttribute::readValueFrom (IStream &is, int, int) +Box2iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.min.x); Xdr::read (is, _value.min.y); @@ -87,7 +88,7 @@ Box2fAttribute::staticTypeName () template <> void -Box2fAttribute::writeValueTo (OStream &os, int) const +Box2fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.min.x); Xdr::write (os, _value.min.y); @@ -98,7 +99,7 @@ Box2fAttribute::writeValueTo (OStream &os, int) const template <> void -Box2fAttribute::readValueFrom (IStream &is, int, int) +Box2fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.min.x); Xdr::read (is, _value.min.y); @@ -107,4 +108,4 @@ Box2fAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfBoxAttribute.h b/3rdparty/openexr/IlmImf/ImfBoxAttribute.h index ca0f1405b2..7bf2585ea2 100644 --- a/3rdparty/openexr/IlmImf/ImfBoxAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfBoxAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,30 +44,44 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfAttribute.h" #include "ImathBox.h" +#include "ImfNamespace.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { +typedef TypedAttribute Box2iAttribute; -typedef TypedAttribute Box2iAttribute; -template <> const char *Box2iAttribute::staticTypeName (); -template <> void Box2iAttribute::writeValueTo (OStream &, int) const; -template <> void Box2iAttribute::readValueFrom (IStream &, int, int); +template <> +IMF_EXPORT +const char *Box2iAttribute::staticTypeName (); +template <> +IMF_EXPORT +void Box2iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; +template <> +IMF_EXPORT +void Box2iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); -typedef TypedAttribute Box2fAttribute; -template <> const char *Box2fAttribute::staticTypeName (); -template <> void Box2fAttribute::writeValueTo (OStream &, int) const; -template <> void Box2fAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute Box2fAttribute; +template <> +IMF_EXPORT +const char *Box2fAttribute::staticTypeName (); +template <> +IMF_EXPORT +void Box2fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; +template <> +IMF_EXPORT +void Box2fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); -} // namespace Imf - -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfCRgbaFile.cpp b/3rdparty/openexr/IlmImf/ImfCRgbaFile.cpp index 7312358574..48363b4742 100644 --- a/3rdparty/openexr/IlmImf/ImfCRgbaFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfCRgbaFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -53,16 +53,20 @@ #include #include #include "half.h" +#include "ImfNamespace.h" +#include "ImathForward.h" + #include -using Imath::Box2i; -using Imath::Box2f; -using Imath::V2i; -using Imath::V2f; -using Imath::V3i; -using Imath::V3f; -using Imath::M33f; -using Imath::M44f; + +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::Box2f; +using IMATH_NAMESPACE::V2i; +using IMATH_NAMESPACE::V2f; +using IMATH_NAMESPACE::V3i; +using IMATH_NAMESPACE::V3f; +using IMATH_NAMESPACE::M33f; +using IMATH_NAMESPACE::M44f; namespace { @@ -80,95 +84,95 @@ setErrorMessage (const std::exception &e) } -inline Imf::Header * +inline OPENEXR_IMF_INTERNAL_NAMESPACE::Header * header (ImfHeader *hdr) { - return (Imf::Header *)(hdr); + return (OPENEXR_IMF_INTERNAL_NAMESPACE::Header *)(hdr); } -inline const Imf::Header * +inline const OPENEXR_IMF_INTERNAL_NAMESPACE::Header * header (const ImfHeader *hdr) { - return (const Imf::Header *)(hdr); + return (const OPENEXR_IMF_INTERNAL_NAMESPACE::Header *)(hdr); } -inline Imf::RgbaOutputFile * +inline OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaOutputFile * outfile (ImfOutputFile *out) { - return (Imf::RgbaOutputFile *) out; + return (OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaOutputFile *) out; } -inline const Imf::RgbaOutputFile * +inline const OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaOutputFile * outfile (const ImfOutputFile *out) { - return (const Imf::RgbaOutputFile *) out; + return (const OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaOutputFile *) out; } -inline Imf::TiledRgbaOutputFile * +inline OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaOutputFile * outfile (ImfTiledOutputFile *out) { - return (Imf::TiledRgbaOutputFile *) out; + return (OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaOutputFile *) out; } -inline const Imf::TiledRgbaOutputFile * +inline const OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaOutputFile * outfile (const ImfTiledOutputFile *out) { - return (const Imf::TiledRgbaOutputFile *) out; + return (const OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaOutputFile *) out; } -inline Imf::RgbaInputFile * +inline OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaInputFile * infile (ImfInputFile *in) { - return (Imf::RgbaInputFile *) in; + return (OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaInputFile *) in; } -inline const Imf::RgbaInputFile * +inline const OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaInputFile * infile (const ImfInputFile *in) { - return (const Imf::RgbaInputFile *) in; + return (const OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaInputFile *) in; } -inline Imf::TiledRgbaInputFile * +inline OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaInputFile * infile (ImfTiledInputFile *in) { - return (Imf::TiledRgbaInputFile *) in; + return (OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaInputFile *) in; } -inline const Imf::TiledRgbaInputFile * +inline const OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaInputFile * infile (const ImfTiledInputFile *in) { - return (const Imf::TiledRgbaInputFile *) in; + return (const OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaInputFile *) in; } } // namespace -void +void ImfFloatToHalf (float f, ImfHalf *h) { *h = half(f).bits(); } -void +void ImfFloatToHalfArray (int n, const float f[/*n*/], ImfHalf h[/*n*/]) { for (int i = 0; i < n; ++i) - h[i] = half(f[i]).bits(); + h[i] = half(f[i]).bits(); } -float +float ImfHalfToFloat (ImfHalf h) { return float (*((half *)&h)); @@ -179,7 +183,7 @@ void ImfHalfToFloatArray (int n, const ImfHalf h[/*n*/], float f[/*n*/]) { for (int i = 0; i < n; ++i) - f[i] = float (*((half *)(h + i))); + f[i] = float (*((half *)(h + i))); } @@ -188,17 +192,17 @@ ImfNewHeader (void) { try { - return (ImfHeader *) new Imf::Header; + return (ImfHeader *) new OPENEXR_IMF_INTERNAL_NAMESPACE::Header; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -void +void ImfDeleteHeader (ImfHeader *hdr) { delete header (hdr); @@ -210,29 +214,29 @@ ImfCopyHeader (const ImfHeader *hdr) { try { - return (ImfHeader *) new Imf::Header (*header (hdr)); + return (ImfHeader *) new OPENEXR_IMF_INTERNAL_NAMESPACE::Header (*header (hdr)); } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -void +void ImfHeaderSetDisplayWindow (ImfHeader *hdr, - int xMin, int yMin, - int xMax, int yMax) + int xMin, int yMin, + int xMax, int yMax) { header(hdr)->displayWindow() = Box2i (V2i (xMin, yMin), V2i (xMax, yMax)); } -void +void ImfHeaderDisplayWindow (const ImfHeader *hdr, - int *xMin, int *yMin, - int *xMax, int *yMax) + int *xMin, int *yMin, + int *xMax, int *yMax) { const Box2i dw = header(hdr)->displayWindow(); *xMin = dw.min.x; @@ -244,17 +248,17 @@ ImfHeaderDisplayWindow (const ImfHeader *hdr, void ImfHeaderSetDataWindow (ImfHeader *hdr, - int xMin, int yMin, - int xMax, int yMax) + int xMin, int yMin, + int xMax, int yMax) { header(hdr)->dataWindow() = Box2i (V2i (xMin, yMin), V2i (xMax, yMax)); } -void +void ImfHeaderDataWindow (const ImfHeader *hdr, - int *xMin, int *yMin, - int *xMax, int *yMax) + int *xMin, int *yMin, + int *xMax, int *yMax) { const Box2i dw = header(hdr)->dataWindow(); *xMin = dw.min.x; @@ -264,165 +268,165 @@ ImfHeaderDataWindow (const ImfHeader *hdr, } -void +void ImfHeaderSetPixelAspectRatio (ImfHeader *hdr, float pixelAspectRatio) { header(hdr)->pixelAspectRatio() = pixelAspectRatio; } -float +float ImfHeaderPixelAspectRatio (const ImfHeader *hdr) { return header(hdr)->pixelAspectRatio(); } -void +void ImfHeaderSetScreenWindowCenter (ImfHeader *hdr, float x, float y) { header(hdr)->screenWindowCenter() = V2f (x, y); } -void +void ImfHeaderScreenWindowCenter (const ImfHeader *hdr, float *x, float *y) { const V2i &swc = header(hdr)->screenWindowCenter(); - *x = swc.x; - *y = swc.y; + *x = (float) swc.x; + *y = (float) swc.y; } -void +void ImfHeaderSetScreenWindowWidth (ImfHeader *hdr, float width) { header(hdr)->screenWindowWidth() = width; } -float +float ImfHeaderScreenWindowWidth (const ImfHeader *hdr) { return header(hdr)->screenWindowWidth(); } -void +void ImfHeaderSetLineOrder (ImfHeader *hdr, int lineOrder) { - header(hdr)->lineOrder() = Imf::LineOrder (lineOrder); + header(hdr)->lineOrder() = OPENEXR_IMF_INTERNAL_NAMESPACE::LineOrder (lineOrder); } -int +int ImfHeaderLineOrder (const ImfHeader *hdr) { return header(hdr)->lineOrder(); } - -void + +void ImfHeaderSetCompression (ImfHeader *hdr, int compression) { - header(hdr)->compression() = Imf::Compression (compression); + header(hdr)->compression() = OPENEXR_IMF_INTERNAL_NAMESPACE::Compression (compression); } -int +int ImfHeaderCompression (const ImfHeader *hdr) { return header(hdr)->compression(); } -int +int ImfHeaderSetIntAttribute (ImfHeader *hdr, const char name[], int value) { try { - if (header(hdr)->find(name) == header(hdr)->end()) - { - header(hdr)->insert (name, Imf::IntAttribute (value)); - } - else - { - header(hdr)->typedAttribute(name).value() = - value; - } + if (header(hdr)->find(name) == header(hdr)->end()) + { + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::IntAttribute (value)); + } + else + { + header(hdr)->typedAttribute(name).value() = + value; + } - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfHeaderIntAttribute (const ImfHeader *hdr, const char name[], int *value) { try { - *value = header(hdr)->typedAttribute(name).value(); - return 1; + *value = header(hdr)->typedAttribute(name).value(); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfHeaderSetFloatAttribute (ImfHeader *hdr, const char name[], float value) { try { - if (header(hdr)->find(name) == header(hdr)->end()) - { - header(hdr)->insert (name, Imf::FloatAttribute (value)); - } - else - { - header(hdr)->typedAttribute(name).value() = - value; - } + if (header(hdr)->find(name) == header(hdr)->end()) + { + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::FloatAttribute (value)); + } + else + { + header(hdr)->typedAttribute(name).value() = + value; + } - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfHeaderSetDoubleAttribute (ImfHeader *hdr, const char name[], double value) { try { - if (header(hdr)->find(name) == header(hdr)->end()) - { - header(hdr)->insert (name, Imf::DoubleAttribute (value)); - } - else - { - header(hdr)->typedAttribute(name).value() = - value; - } + if (header(hdr)->find(name) == header(hdr)->end()) + { + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::DoubleAttribute (value)); + } + else + { + header(hdr)->typedAttribute(name).value() = + value; + } - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -432,569 +436,569 @@ ImfHeaderFloatAttribute (const ImfHeader *hdr, const char name[], float *value) { try { - *value = header(hdr)->typedAttribute(name).value(); - return 1; + *value = header(hdr)->typedAttribute(name).value(); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderDoubleAttribute (const ImfHeader *hdr, - const char name[], - double *value) + const char name[], + double *value) { try { - *value = header(hdr)-> - typedAttribute(name).value(); + *value = header(hdr)-> + typedAttribute(name).value(); - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderSetStringAttribute (ImfHeader *hdr, - const char name[], - const char value[]) + const char name[], + const char value[]) { try { - if (header(hdr)->find(name) == header(hdr)->end()) - { - header(hdr)->insert (name, Imf::StringAttribute (value)); - } - else - { - header(hdr)->typedAttribute(name).value() = - value; - } + if (header(hdr)->find(name) == header(hdr)->end()) + { + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::StringAttribute (value)); + } + else + { + header(hdr)->typedAttribute(name).value() = + value; + } - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderStringAttribute (const ImfHeader *hdr, - const char name[], - const char **value) + const char name[], + const char **value) { try { - *value = header(hdr)-> - typedAttribute(name).value().c_str(); + *value = header(hdr)-> + typedAttribute(name).value().c_str(); - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderSetBox2iAttribute (ImfHeader *hdr, - const char name[], - int xMin, int yMin, - int xMax, int yMax) + const char name[], + int xMin, int yMin, + int xMax, int yMax) { try { - Box2i box (V2i (xMin, yMin), V2i (xMax, yMax)); + Box2i box (V2i (xMin, yMin), V2i (xMax, yMax)); - if (header(hdr)->find(name) == header(hdr)->end()) - { - header(hdr)->insert (name, Imf::Box2iAttribute (box)); - } - else - { - header(hdr)->typedAttribute(name).value() = - box; - } + if (header(hdr)->find(name) == header(hdr)->end()) + { + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::Box2iAttribute (box)); + } + else + { + header(hdr)->typedAttribute(name).value() = + box; + } - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderBox2iAttribute (const ImfHeader *hdr, - const char name[], - int *xMin, int *yMin, - int *xMax, int *yMax) + const char name[], + int *xMin, int *yMin, + int *xMax, int *yMax) { try { - const Box2i &box = - header(hdr)->typedAttribute(name).value(); + const Box2i &box = + header(hdr)->typedAttribute(name).value(); - *xMin = box.min.x; - *yMin = box.min.y; - *xMax = box.max.x; - *yMax = box.max.y; + *xMin = box.min.x; + *yMin = box.min.y; + *xMax = box.max.x; + *yMax = box.max.y; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderSetBox2fAttribute (ImfHeader *hdr, - const char name[], - float xMin, float yMin, - float xMax, float yMax) + const char name[], + float xMin, float yMin, + float xMax, float yMax) { try { - Box2f box (V2f (xMin, yMin), V2f (xMax, yMax)); + Box2f box (V2f (xMin, yMin), V2f (xMax, yMax)); - if (header(hdr)->find(name) == header(hdr)->end()) - { - header(hdr)->insert (name, Imf::Box2fAttribute (box)); - } - else - { - header(hdr)->typedAttribute(name).value() = - box; - } + if (header(hdr)->find(name) == header(hdr)->end()) + { + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::Box2fAttribute (box)); + } + else + { + header(hdr)->typedAttribute(name).value() = + box; + } - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderBox2fAttribute (const ImfHeader *hdr, - const char name[], - float *xMin, float *yMin, - float *xMax, float *yMax) + const char name[], + float *xMin, float *yMin, + float *xMax, float *yMax) { try { - const Box2f &box = - header(hdr)->typedAttribute(name).value(); + const Box2f &box = + header(hdr)->typedAttribute(name).value(); - *xMin = box.min.x; - *yMin = box.min.y; - *xMax = box.max.x; - *yMax = box.max.y; + *xMin = box.min.x; + *yMin = box.min.y; + *xMax = box.max.x; + *yMax = box.max.y; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderSetV2iAttribute (ImfHeader *hdr, - const char name[], - int x, int y) + const char name[], + int x, int y) { try { - V2i v (x, y); + V2i v (x, y); - if (header(hdr)->find(name) == header(hdr)->end()) - header(hdr)->insert (name, Imf::V2iAttribute (v)); - else - header(hdr)->typedAttribute(name).value() = v; + if (header(hdr)->find(name) == header(hdr)->end()) + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::V2iAttribute (v)); + else + header(hdr)->typedAttribute(name).value() = v; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderV2iAttribute (const ImfHeader *hdr, - const char name[], - int *x, int *y) + const char name[], + int *x, int *y) { try { - const V2i &v = - header(hdr)->typedAttribute(name).value(); + const V2i &v = + header(hdr)->typedAttribute(name).value(); - *x = v.x; - *y = v.y; + *x = v.x; + *y = v.y; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfHeaderSetV2fAttribute (ImfHeader *hdr, - const char name[], - float x, float y) + const char name[], + float x, float y) { try { - V2f v (x, y); + V2f v (x, y); - if (header(hdr)->find(name) == header(hdr)->end()) - header(hdr)->insert (name, Imf::V2fAttribute (v)); - else - header(hdr)->typedAttribute(name).value() = v; + if (header(hdr)->find(name) == header(hdr)->end()) + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::V2fAttribute (v)); + else + header(hdr)->typedAttribute(name).value() = v; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderV2fAttribute (const ImfHeader *hdr, - const char name[], - float *x, float *y) + const char name[], + float *x, float *y) { try { - const V2f &v = - header(hdr)->typedAttribute(name).value(); + const V2f &v = + header(hdr)->typedAttribute(name).value(); - *x = v.x; - *y = v.y; + *x = v.x; + *y = v.y; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderSetV3iAttribute (ImfHeader *hdr, - const char name[], - int x, int y, int z) + const char name[], + int x, int y, int z) { try { - V3i v (x, y, z); + V3i v (x, y, z); - if (header(hdr)->find(name) == header(hdr)->end()) - header(hdr)->insert (name, Imf::V3iAttribute (v)); - else - header(hdr)->typedAttribute(name).value() = v; + if (header(hdr)->find(name) == header(hdr)->end()) + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::V3iAttribute (v)); + else + header(hdr)->typedAttribute(name).value() = v; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderV3iAttribute (const ImfHeader *hdr, - const char name[], - int *x, int *y, int *z) + const char name[], + int *x, int *y, int *z) { try { - const V3i &v = - header(hdr)->typedAttribute(name).value(); + const V3i &v = + header(hdr)->typedAttribute(name).value(); - *x = v.x; - *y = v.y; - *z = v.z; + *x = v.x; + *y = v.y; + *z = v.z; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderSetV3fAttribute (ImfHeader *hdr, - const char name[], - float x, float y, float z) + const char name[], + float x, float y, float z) { try { - V3f v (x, y, z); + V3f v (x, y, z); - if (header(hdr)->find(name) == header(hdr)->end()) - header(hdr)->insert (name, Imf::V3fAttribute (v)); - else - header(hdr)->typedAttribute(name).value() = v; + if (header(hdr)->find(name) == header(hdr)->end()) + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::V3fAttribute (v)); + else + header(hdr)->typedAttribute(name).value() = v; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderV3fAttribute (const ImfHeader *hdr, - const char name[], - float *x, float *y, float *z) + const char name[], + float *x, float *y, float *z) { try { - const V3f &v = - header(hdr)->typedAttribute(name).value(); + const V3f &v = + header(hdr)->typedAttribute(name).value(); - *x = v.x; - *y = v.y; - *z = v.z; + *x = v.x; + *y = v.y; + *z = v.z; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderSetM33fAttribute (ImfHeader *hdr, - const char name[], - const float m[3][3]) + const char name[], + const float m[3][3]) { try { - M33f m3 (m); + M33f m3 (m); - if (header(hdr)->find(name) == header(hdr)->end()) - header(hdr)->insert (name, Imf::M33fAttribute (m3)); - else - header(hdr)->typedAttribute(name).value() = m3; + if (header(hdr)->find(name) == header(hdr)->end()) + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::M33fAttribute (m3)); + else + header(hdr)->typedAttribute(name).value() = m3; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderM33fAttribute (const ImfHeader *hdr, - const char name[], - float m[3][3]) + const char name[], + float m[3][3]) { try { - const M33f &m3 = - header(hdr)->typedAttribute(name).value(); + const M33f &m3 = + header(hdr)->typedAttribute(name).value(); - m[0][0] = m3[0][0]; - m[0][1] = m3[0][1]; - m[0][2] = m3[0][2]; + m[0][0] = m3[0][0]; + m[0][1] = m3[0][1]; + m[0][2] = m3[0][2]; - m[1][0] = m3[1][0]; - m[1][1] = m3[1][1]; - m[1][2] = m3[1][2]; + m[1][0] = m3[1][0]; + m[1][1] = m3[1][1]; + m[1][2] = m3[1][2]; - m[2][0] = m3[2][0]; - m[2][1] = m3[2][1]; - m[2][2] = m3[2][2]; + m[2][0] = m3[2][0]; + m[2][1] = m3[2][1]; + m[2][2] = m3[2][2]; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderSetM44fAttribute (ImfHeader *hdr, - const char name[], - const float m[4][4]) + const char name[], + const float m[4][4]) { try { - M44f m4 (m); + M44f m4 (m); - if (header(hdr)->find(name) == header(hdr)->end()) - header(hdr)->insert (name, Imf::M44fAttribute (m4)); - else - header(hdr)->typedAttribute(name).value() = m4; + if (header(hdr)->find(name) == header(hdr)->end()) + header(hdr)->insert (name, OPENEXR_IMF_INTERNAL_NAMESPACE::M44fAttribute (m4)); + else + header(hdr)->typedAttribute(name).value() = m4; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfHeaderM44fAttribute (const ImfHeader *hdr, - const char name[], - float m[4][4]) + const char name[], + float m[4][4]) { try { - const M44f &m4 = - header(hdr)->typedAttribute(name).value(); + const M44f &m4 = + header(hdr)->typedAttribute(name).value(); - m[0][0] = m4[0][0]; - m[0][1] = m4[0][1]; - m[0][2] = m4[0][2]; - m[0][3] = m4[0][3]; + m[0][0] = m4[0][0]; + m[0][1] = m4[0][1]; + m[0][2] = m4[0][2]; + m[0][3] = m4[0][3]; - m[1][0] = m4[1][0]; - m[1][1] = m4[1][1]; - m[1][2] = m4[1][2]; - m[1][3] = m4[1][3]; + m[1][0] = m4[1][0]; + m[1][1] = m4[1][1]; + m[1][2] = m4[1][2]; + m[1][3] = m4[1][3]; - m[2][0] = m4[2][0]; - m[2][1] = m4[2][1]; - m[2][2] = m4[2][2]; - m[2][3] = m4[2][3]; + m[2][0] = m4[2][0]; + m[2][1] = m4[2][1]; + m[2][2] = m4[2][2]; + m[2][3] = m4[2][3]; - m[3][0] = m4[3][0]; - m[3][1] = m4[3][1]; - m[3][2] = m4[3][2]; - m[3][3] = m4[3][3]; + m[3][0] = m4[3][0]; + m[3][1] = m4[3][1]; + m[3][2] = m4[3][2]; + m[3][3] = m4[3][3]; - return 1; + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -ImfOutputFile * +ImfOutputFile * ImfOpenOutputFile (const char name[], const ImfHeader *hdr, int channels) { try { - return (ImfOutputFile *) new Imf::RgbaOutputFile - (name, *header(hdr), Imf::RgbaChannels (channels)); + return (ImfOutputFile *) new OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaOutputFile + (name, *header(hdr), OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaChannels (channels)); } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfCloseOutputFile (ImfOutputFile *out) { try { - delete outfile (out); - return 1; + delete outfile (out); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfOutputSetFrameBuffer (ImfOutputFile *out, - const ImfRgba *base, - size_t xStride, - size_t yStride) + const ImfRgba *base, + size_t xStride, + size_t yStride) { try { - outfile(out)->setFrameBuffer ((Imf::Rgba *)base, xStride, yStride); - return 1; + outfile(out)->setFrameBuffer ((OPENEXR_IMF_INTERNAL_NAMESPACE::Rgba *)base, xStride, yStride); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfOutputWritePixels (ImfOutputFile *out, int numScanLines) { try { - outfile(out)->writePixels (numScanLines); - return 1; + outfile(out)->writePixels (numScanLines); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1020,98 +1024,98 @@ ImfOutputChannels (const ImfOutputFile *out) } -ImfTiledOutputFile * +ImfTiledOutputFile * ImfOpenTiledOutputFile (const char name[], - const ImfHeader *hdr, - int channels, - int xSize, int ySize, - int mode, int rmode) + const ImfHeader *hdr, + int channels, + int xSize, int ySize, + int mode, int rmode) { try { - return (ImfTiledOutputFile *) new Imf::TiledRgbaOutputFile - (name, *header(hdr), - Imf::RgbaChannels (channels), - xSize, ySize, - Imf::LevelMode (mode), - Imf::LevelRoundingMode (rmode)); + return (ImfTiledOutputFile *) new OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaOutputFile + (name, *header(hdr), + OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaChannels (channels), + xSize, ySize, + OPENEXR_IMF_INTERNAL_NAMESPACE::LevelMode (mode), + OPENEXR_IMF_INTERNAL_NAMESPACE::LevelRoundingMode (rmode)); } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfCloseTiledOutputFile (ImfTiledOutputFile *out) { try { - delete outfile (out); - return 1; + delete outfile (out); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfTiledOutputSetFrameBuffer (ImfTiledOutputFile *out, - const ImfRgba *base, - size_t xStride, - size_t yStride) + const ImfRgba *base, + size_t xStride, + size_t yStride) { try { - outfile(out)->setFrameBuffer ((Imf::Rgba *)base, xStride, yStride); - return 1; + outfile(out)->setFrameBuffer ((OPENEXR_IMF_INTERNAL_NAMESPACE::Rgba *)base, xStride, yStride); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfTiledOutputWriteTile (ImfTiledOutputFile *out, - int dx, int dy, - int lx, int ly) + int dx, int dy, + int lx, int ly) { try { - outfile(out)->writeTile (dx, dy, lx, ly); - return 1; + outfile(out)->writeTile (dx, dy, lx, ly); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfTiledOutputWriteTiles (ImfTiledOutputFile *out, - int dxMin, int dxMax, + int dxMin, int dxMax, int dyMin, int dyMax, - int lx, int ly) + int lx, int ly) { try { - outfile(out)->writeTiles (dxMin, dxMax, dyMin, dyMax, lx, ly); - return 1; + outfile(out)->writeTiles (dxMin, dxMax, dyMin, dyMax, lx, ly); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1158,17 +1162,17 @@ ImfTiledOutputLevelRoundingMode (const ImfTiledOutputFile *out) } -ImfInputFile * +ImfInputFile * ImfOpenInputFile (const char name[]) { try { - return (ImfInputFile *) new Imf::RgbaInputFile (name); + return (ImfInputFile *) new OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaInputFile (name); } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1178,32 +1182,32 @@ ImfCloseInputFile (ImfInputFile *in) { try { - delete infile (in); - return 1; + delete infile (in); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfInputSetFrameBuffer (ImfInputFile *in, - ImfRgba *base, - size_t xStride, - size_t yStride) + ImfRgba *base, + size_t xStride, + size_t yStride) { try { - infile(in)->setFrameBuffer ((Imf::Rgba *) base, xStride, yStride); - return 1; + infile(in)->setFrameBuffer ((OPENEXR_IMF_INTERNAL_NAMESPACE::Rgba *) base, xStride, yStride); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1213,13 +1217,13 @@ ImfInputReadPixels (ImfInputFile *in, int scanLine1, int scanLine2) { try { - infile(in)->readPixels (scanLine1, scanLine2); - return 1; + infile(in)->readPixels (scanLine1, scanLine2); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1245,17 +1249,17 @@ ImfInputFileName (const ImfInputFile *in) } -ImfTiledInputFile * +ImfTiledInputFile * ImfOpenTiledInputFile (const char name[]) { try { - return (ImfTiledInputFile *) new Imf::TiledRgbaInputFile (name); + return (ImfTiledInputFile *) new OPENEXR_IMF_INTERNAL_NAMESPACE::TiledRgbaInputFile (name); } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1265,69 +1269,69 @@ ImfCloseTiledInputFile (ImfTiledInputFile *in) { try { - delete infile (in); - return 1; + delete infile (in); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } -int +int ImfTiledInputSetFrameBuffer (ImfTiledInputFile *in, - ImfRgba *base, - size_t xStride, - size_t yStride) + ImfRgba *base, + size_t xStride, + size_t yStride) { try { - infile(in)->setFrameBuffer ((Imf::Rgba *) base, xStride, yStride); - return 1; + infile(in)->setFrameBuffer ((OPENEXR_IMF_INTERNAL_NAMESPACE::Rgba *) base, xStride, yStride); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfTiledInputReadTile (ImfTiledInputFile *in, - int dx, int dy, - int lx, int ly) + int dx, int dy, + int lx, int ly) { try { - infile(in)->readTile (dx, dy, lx, ly); - return 1; + infile(in)->readTile (dx, dy, lx, ly); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } int ImfTiledInputReadTiles (ImfTiledInputFile *in, - int dxMin, int dxMax, + int dxMin, int dxMax, int dyMin, int dyMax, - int lx, int ly) + int lx, int ly) { try { - infile(in)->readTiles (dxMin, dxMax, dyMin, dyMax, lx, ly); - return 1; + infile(in)->readTiles (dxMin, dxMax, dyMin, dyMax, lx, ly); + return 1; } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1386,13 +1390,13 @@ ImfNewRound12logLut (int channels) { try { - return (ImfLut *) new Imf::RgbaLut - (Imf::round12log, Imf::RgbaChannels (channels)); + return (ImfLut *) new OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaLut + (OPENEXR_IMF_INTERNAL_NAMESPACE::round12log, OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaChannels (channels)); } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1402,13 +1406,13 @@ ImfNewRoundNBitLut (unsigned int n, int channels) { try { - return (ImfLut *) new Imf::RgbaLut - (Imf::roundNBit (n), Imf::RgbaChannels (channels)); + return (ImfLut *) new OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaLut + (OPENEXR_IMF_INTERNAL_NAMESPACE::roundNBit (n), OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaChannels (channels)); } catch (const std::exception &e) { - setErrorMessage (e); - return 0; + setErrorMessage (e); + return 0; } } @@ -1416,18 +1420,18 @@ ImfNewRoundNBitLut (unsigned int n, int channels) void ImfDeleteLut (ImfLut *lut) { - delete (Imf::RgbaLut *) lut; + delete (OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaLut *) lut; } void ImfApplyLut (ImfLut *lut, ImfRgba *data, int nData, int stride) { - ((Imf::RgbaLut *)lut)->apply ((Imf::Rgba *)data, nData, stride); + ((OPENEXR_IMF_INTERNAL_NAMESPACE::RgbaLut *)lut)->apply ((OPENEXR_IMF_INTERNAL_NAMESPACE::Rgba *)data, nData, stride); } -const char * +const char * ImfErrorMessage () { return errorMessage; diff --git a/3rdparty/openexr/IlmImf/ImfCRgbaFile.h b/3rdparty/openexr/IlmImf/ImfCRgbaFile.h index 7921069292..db5824781a 100644 --- a/3rdparty/openexr/IlmImf/ImfCRgbaFile.h +++ b/3rdparty/openexr/IlmImf/ImfCRgbaFile.h @@ -16,7 +16,7 @@ in the documentation and/or other materials provided with the distribution. * Neither the name of Industrial Light & Magic nor the names of its contributors may be used to endorse or promote products derived -from this software without specific prior written permission. +from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -35,6 +35,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_IMF_C_RGBA_FILE_H #define INCLUDED_IMF_C_RGBA_FILE_H +#include "ImfExport.h" #include @@ -48,18 +49,22 @@ extern "C" { typedef unsigned short ImfHalf; +IMF_EXPORT void ImfFloatToHalf (float f, - ImfHalf *h); + ImfHalf *h); +IMF_EXPORT void ImfFloatToHalfArray (int n, - const float f[/*n*/], - ImfHalf h[/*n*/]); + const float f[/*n*/], + ImfHalf h[/*n*/]); +IMF_EXPORT float ImfHalfToFloat (ImfHalf h); +IMF_EXPORT void ImfHalfToFloatArray (int n, - const ImfHalf h[/*n*/], - float f[/*n*/]); + const ImfHalf h[/*n*/], + float f[/*n*/]); /* ** RGBA pixel; memory layout must be the same as struct Imf::Rgba. @@ -93,7 +98,7 @@ typedef struct ImfRgba ImfRgba; #define IMF_INCREASING_Y 0 #define IMF_DECREASING_Y 1 -#define IMF_RAMDOM_Y 2 +#define IMF_RANDOM_Y 2 /* @@ -151,153 +156,194 @@ typedef struct ImfRgba ImfRgba; struct ImfHeader; typedef struct ImfHeader ImfHeader; +IMF_EXPORT ImfHeader * ImfNewHeader (void); +IMF_EXPORT void ImfDeleteHeader (ImfHeader *hdr); +IMF_EXPORT ImfHeader * ImfCopyHeader (const ImfHeader *hdr); +IMF_EXPORT void ImfHeaderSetDisplayWindow (ImfHeader *hdr, - int xMin, int yMin, - int xMax, int yMax); + int xMin, int yMin, + int xMax, int yMax); +IMF_EXPORT void ImfHeaderDisplayWindow (const ImfHeader *hdr, - int *xMin, int *yMin, - int *xMax, int *yMax); + int *xMin, int *yMin, + int *xMax, int *yMax); +IMF_EXPORT void ImfHeaderSetDataWindow (ImfHeader *hdr, - int xMin, int yMin, - int xMax, int yMax); + int xMin, int yMin, + int xMax, int yMax); +IMF_EXPORT void ImfHeaderDataWindow (const ImfHeader *hdr, - int *xMin, int *yMin, - int *xMax, int *yMax); + int *xMin, int *yMin, + int *xMax, int *yMax); +IMF_EXPORT void ImfHeaderSetPixelAspectRatio (ImfHeader *hdr, - float pixelAspectRatio); + float pixelAspectRatio); +IMF_EXPORT float ImfHeaderPixelAspectRatio (const ImfHeader *hdr); +IMF_EXPORT void ImfHeaderSetScreenWindowCenter (ImfHeader *hdr, - float x, float y); + float x, float y); +IMF_EXPORT void ImfHeaderScreenWindowCenter (const ImfHeader *hdr, - float *x, float *y); + float *x, float *y); +IMF_EXPORT void ImfHeaderSetScreenWindowWidth (ImfHeader *hdr, - float width); + float width); +IMF_EXPORT float ImfHeaderScreenWindowWidth (const ImfHeader *hdr); +IMF_EXPORT void ImfHeaderSetLineOrder (ImfHeader *hdr, - int lineOrder); + int lineOrder); +IMF_EXPORT int ImfHeaderLineOrder (const ImfHeader *hdr); - + +IMF_EXPORT void ImfHeaderSetCompression (ImfHeader *hdr, - int compression); + int compression); +IMF_EXPORT int ImfHeaderCompression (const ImfHeader *hdr); +IMF_EXPORT int ImfHeaderSetIntAttribute (ImfHeader *hdr, - const char name[], - int value); + const char name[], + int value); +IMF_EXPORT int ImfHeaderIntAttribute (const ImfHeader *hdr, - const char name[], - int *value); + const char name[], + int *value); +IMF_EXPORT int ImfHeaderSetFloatAttribute (ImfHeader *hdr, - const char name[], - float value); + const char name[], + float value); +IMF_EXPORT int ImfHeaderSetDoubleAttribute (ImfHeader *hdr, - const char name[], - double value); + const char name[], + double value); +IMF_EXPORT int ImfHeaderFloatAttribute (const ImfHeader *hdr, - const char name[], - float *value); + const char name[], + float *value); +IMF_EXPORT int ImfHeaderDoubleAttribute (const ImfHeader *hdr, - const char name[], - double *value); + const char name[], + double *value); +IMF_EXPORT int ImfHeaderSetStringAttribute (ImfHeader *hdr, - const char name[], - const char value[]); + const char name[], + const char value[]); +IMF_EXPORT int ImfHeaderStringAttribute (const ImfHeader *hdr, - const char name[], - const char **value); + const char name[], + const char **value); +IMF_EXPORT int ImfHeaderSetBox2iAttribute (ImfHeader *hdr, - const char name[], - int xMin, int yMin, - int xMax, int yMax); + const char name[], + int xMin, int yMin, + int xMax, int yMax); +IMF_EXPORT int ImfHeaderBox2iAttribute (const ImfHeader *hdr, - const char name[], - int *xMin, int *yMin, - int *xMax, int *yMax); + const char name[], + int *xMin, int *yMin, + int *xMax, int *yMax); +IMF_EXPORT int ImfHeaderSetBox2fAttribute (ImfHeader *hdr, - const char name[], - float xMin, float yMin, - float xMax, float yMax); + const char name[], + float xMin, float yMin, + float xMax, float yMax); +IMF_EXPORT int ImfHeaderBox2fAttribute (const ImfHeader *hdr, - const char name[], - float *xMin, float *yMin, - float *xMax, float *yMax); + const char name[], + float *xMin, float *yMin, + float *xMax, float *yMax); +IMF_EXPORT int ImfHeaderSetV2iAttribute (ImfHeader *hdr, - const char name[], - int x, int y); + const char name[], + int x, int y); +IMF_EXPORT int ImfHeaderV2iAttribute (const ImfHeader *hdr, - const char name[], - int *x, int *y); + const char name[], + int *x, int *y); +IMF_EXPORT int ImfHeaderSetV2fAttribute (ImfHeader *hdr, - const char name[], - float x, float y); + const char name[], + float x, float y); +IMF_EXPORT int ImfHeaderV2fAttribute (const ImfHeader *hdr, - const char name[], - float *x, float *y); + const char name[], + float *x, float *y); +IMF_EXPORT int ImfHeaderSetV3iAttribute (ImfHeader *hdr, - const char name[], - int x, int y, int z); + const char name[], + int x, int y, int z); +IMF_EXPORT int ImfHeaderV3iAttribute (const ImfHeader *hdr, - const char name[], - int *x, int *y, int *z); + const char name[], + int *x, int *y, int *z); +IMF_EXPORT int ImfHeaderSetV3fAttribute (ImfHeader *hdr, - const char name[], - float x, float y, float z); + const char name[], + float x, float y, float z); +IMF_EXPORT int ImfHeaderV3fAttribute (const ImfHeader *hdr, - const char name[], - float *x, float *y, float *z); + const char name[], + float *x, float *y, float *z); +IMF_EXPORT int ImfHeaderSetM33fAttribute (ImfHeader *hdr, - const char name[], - const float m[3][3]); + const char name[], + const float m[3][3]); +IMF_EXPORT int ImfHeaderM33fAttribute (const ImfHeader *hdr, - const char name[], - float m[3][3]); + const char name[], + float m[3][3]); +IMF_EXPORT int ImfHeaderSetM44fAttribute (ImfHeader *hdr, - const char name[], - const float m[4][4]); + const char name[], + const float m[4][4]); +IMF_EXPORT int ImfHeaderM44fAttribute (const ImfHeader *hdr, - const char name[], - float m[4][4]); + const char name[], + float m[4][4]); /* ** RGBA output file @@ -306,24 +352,31 @@ int ImfHeaderM44fAttribute (const ImfHeader *hdr, struct ImfOutputFile; typedef struct ImfOutputFile ImfOutputFile; +IMF_EXPORT ImfOutputFile * ImfOpenOutputFile (const char name[], - const ImfHeader *hdr, - int channels); + const ImfHeader *hdr, + int channels); +IMF_EXPORT int ImfCloseOutputFile (ImfOutputFile *out); +IMF_EXPORT int ImfOutputSetFrameBuffer (ImfOutputFile *out, - const ImfRgba *base, - size_t xStride, - size_t yStride); + const ImfRgba *base, + size_t xStride, + size_t yStride); +IMF_EXPORT int ImfOutputWritePixels (ImfOutputFile *out, - int numScanLines); + int numScanLines); +IMF_EXPORT int ImfOutputCurrentScanLine (const ImfOutputFile *out); +IMF_EXPORT const ImfHeader * ImfOutputHeader (const ImfOutputFile *out); +IMF_EXPORT int ImfOutputChannels (const ImfOutputFile *out); @@ -334,39 +387,51 @@ int ImfOutputChannels (const ImfOutputFile *out); struct ImfTiledOutputFile; typedef struct ImfTiledOutputFile ImfTiledOutputFile; +IMF_EXPORT ImfTiledOutputFile * ImfOpenTiledOutputFile (const char name[], - const ImfHeader *hdr, - int channels, - int xSize, int ySize, - int mode, int rmode); + const ImfHeader *hdr, + int channels, + int xSize, int ySize, + int mode, int rmode); +IMF_EXPORT int ImfCloseTiledOutputFile (ImfTiledOutputFile *out); +IMF_EXPORT int ImfTiledOutputSetFrameBuffer (ImfTiledOutputFile *out, - const ImfRgba *base, - size_t xStride, - size_t yStride); + const ImfRgba *base, + size_t xStride, + size_t yStride); +IMF_EXPORT int ImfTiledOutputWriteTile (ImfTiledOutputFile *out, - int dx, int dy, - int lx, int ly); + int dx, int dy, + int lx, int ly); +IMF_EXPORT int ImfTiledOutputWriteTiles (ImfTiledOutputFile *out, int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly); +IMF_EXPORT const ImfHeader * ImfTiledOutputHeader (const ImfTiledOutputFile *out); +IMF_EXPORT int ImfTiledOutputChannels (const ImfTiledOutputFile *out); +IMF_EXPORT int ImfTiledOutputTileXSize (const ImfTiledOutputFile *out); +IMF_EXPORT int ImfTiledOutputTileYSize (const ImfTiledOutputFile *out); +IMF_EXPORT int ImfTiledOutputLevelMode (const ImfTiledOutputFile *out); + +IMF_EXPORT int ImfTiledOutputLevelRoundingMode - (const ImfTiledOutputFile *out); + (const ImfTiledOutputFile *out); /* @@ -378,21 +443,27 @@ typedef struct ImfInputFile ImfInputFile; ImfInputFile * ImfOpenInputFile (const char name[]); +IMF_EXPORT int ImfCloseInputFile (ImfInputFile *in); +IMF_EXPORT int ImfInputSetFrameBuffer (ImfInputFile *in, - ImfRgba *base, - size_t xStride, - size_t yStride); + ImfRgba *base, + size_t xStride, + size_t yStride); +IMF_EXPORT int ImfInputReadPixels (ImfInputFile *in, - int scanLine1, - int scanLine2); + int scanLine1, + int scanLine2); +IMF_EXPORT const ImfHeader * ImfInputHeader (const ImfInputFile *in); +IMF_EXPORT int ImfInputChannels (const ImfInputFile *in); +IMF_EXPORT const char * ImfInputFileName (const ImfInputFile *in); @@ -403,38 +474,50 @@ const char * ImfInputFileName (const ImfInputFile *in); struct ImfTiledInputFile; typedef struct ImfTiledInputFile ImfTiledInputFile; +IMF_EXPORT ImfTiledInputFile * ImfOpenTiledInputFile (const char name[]); +IMF_EXPORT int ImfCloseTiledInputFile (ImfTiledInputFile *in); +IMF_EXPORT int ImfTiledInputSetFrameBuffer (ImfTiledInputFile *in, - ImfRgba *base, - size_t xStride, - size_t yStride); + ImfRgba *base, + size_t xStride, + size_t yStride); +IMF_EXPORT int ImfTiledInputReadTile (ImfTiledInputFile *in, - int dx, int dy, - int lx, int ly); + int dx, int dy, + int lx, int ly); +IMF_EXPORT int ImfTiledInputReadTiles (ImfTiledInputFile *in, int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly); +IMF_EXPORT const ImfHeader * ImfTiledInputHeader (const ImfTiledInputFile *in); +IMF_EXPORT int ImfTiledInputChannels (const ImfTiledInputFile *in); +IMF_EXPORT const char * ImfTiledInputFileName (const ImfTiledInputFile *in); +IMF_EXPORT int ImfTiledInputTileXSize (const ImfTiledInputFile *in); +IMF_EXPORT int ImfTiledInputTileYSize (const ImfTiledInputFile *in); +IMF_EXPORT int ImfTiledInputLevelMode (const ImfTiledInputFile *in); +IMF_EXPORT int ImfTiledInputLevelRoundingMode - (const ImfTiledInputFile *in); + (const ImfTiledInputFile *in); /* ** Lookup tables @@ -443,20 +526,25 @@ int ImfTiledInputLevelRoundingMode struct ImfLut; typedef struct ImfLut ImfLut; +IMF_EXPORT ImfLut * ImfNewRound12logLut (int channels); +IMF_EXPORT ImfLut * ImfNewRoundNBitLut (unsigned int n, int channels); +IMF_EXPORT void ImfDeleteLut (ImfLut *lut); +IMF_EXPORT void ImfApplyLut (ImfLut *lut, - ImfRgba *data, - int nData, - int stride); + ImfRgba *data, + int nData, + int stride); /* ** Most recent error message */ +IMF_EXPORT const char * ImfErrorMessage (void); diff --git a/3rdparty/openexr/IlmImf/ImfChannelList.cpp b/3rdparty/openexr/IlmImf/ImfChannelList.cpp index 4a74c97d4c..ae2ccaa45e 100644 --- a/3rdparty/openexr/IlmImf/ImfChannelList.cpp +++ b/3rdparty/openexr/IlmImf/ImfChannelList.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -47,8 +47,9 @@ using std::string; using std::set; +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER Channel::Channel (PixelType t, int xs, int ys, bool pl): @@ -61,27 +62,27 @@ Channel::Channel (PixelType t, int xs, int ys, bool pl): } -bool +bool Channel::operator == (const Channel &other) const { return type == other.type && - xSampling == other.xSampling && - ySampling == other.ySampling && - pLinear == other.pLinear; + xSampling == other.xSampling && + ySampling == other.ySampling && + pLinear == other.pLinear; } -void +void ChannelList::insert (const char name[], const Channel &channel) { if (name[0] == 0) - THROW (Iex::ArgExc, "Image channel name cannot be an empty string."); + THROW (IEX_NAMESPACE::ArgExc, "Image channel name cannot be an empty string."); _map[name] = channel; } -void +void ChannelList::insert (const string &name, const Channel &channel) { insert (name.c_str(), channel); @@ -94,7 +95,7 @@ ChannelList::operator [] (const char name[]) ChannelMap::iterator i = _map.find (name); if (i == _map.end()) - THROW (Iex::ArgExc, "Cannot find image channel \"" << name << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "Cannot find image channel \"" << name << "\"."); return i->second; } @@ -106,7 +107,7 @@ ChannelList::operator [] (const char name[]) const ChannelMap::const_iterator i = _map.find (name); if (i == _map.end()) - THROW (Iex::ArgExc, "Cannot find image channel \"" << name << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "Cannot find image channel \"" << name << "\"."); return i->second; } @@ -156,14 +157,14 @@ ChannelList::findChannel (const string &name) const } -ChannelList::Iterator +ChannelList::Iterator ChannelList::begin () { return _map.begin(); } -ChannelList::ConstIterator +ChannelList::ConstIterator ChannelList::begin () const { return _map.begin(); @@ -177,7 +178,7 @@ ChannelList::end () } -ChannelList::ConstIterator +ChannelList::ConstIterator ChannelList::end () const { return _map.end(); @@ -219,22 +220,22 @@ ChannelList::layers (set &layerNames) const for (ConstIterator i = begin(); i != end(); ++i) { - string layerName = i.name(); - size_t pos = layerName.rfind ('.'); - - if (pos != string::npos && pos != 0 && pos + 1 < layerName.size()) - { - layerName.erase (pos); - layerNames.insert (layerName); - } + string layerName = i.name(); + size_t pos = layerName.rfind ('.'); + + if (pos != string::npos && pos != 0 && pos + 1 < layerName.size()) + { + layerName.erase (pos); + layerNames.insert (layerName); + } } } void ChannelList::channelsInLayer (const string &layerName, - Iterator &first, - Iterator &last) + Iterator &first, + Iterator &last) { channelsWithPrefix (layerName + '.', first, last); } @@ -242,49 +243,49 @@ ChannelList::channelsInLayer (const string &layerName, void ChannelList::channelsInLayer (const string &layerName, - ConstIterator &first, - ConstIterator &last) const + ConstIterator &first, + ConstIterator &last) const { channelsWithPrefix (layerName + '.', first, last); } -void +void ChannelList::channelsWithPrefix (const char prefix[], - Iterator &first, - Iterator &last) + Iterator &first, + Iterator &last) { first = last = _map.lower_bound (prefix); - int n = strlen (prefix); + size_t n = int(strlen (prefix)); while (last != Iterator (_map.end()) && - strncmp (last.name(), prefix, n) <= 0) + strncmp (last.name(), prefix, n) <= 0) { - ++last; + ++last; } } void ChannelList::channelsWithPrefix (const char prefix[], - ConstIterator &first, - ConstIterator &last) const + ConstIterator &first, + ConstIterator &last) const { first = last = _map.lower_bound (prefix); - int n = strlen (prefix); + size_t n = strlen (prefix); while (last != ConstIterator (_map.end()) && - strncmp (last.name(), prefix, n) <= 0) + strncmp (last.name(), prefix, n) <= 0) { - ++last; + ++last; } } -void +void ChannelList::channelsWithPrefix (const string &prefix, - Iterator &first, - Iterator &last) + Iterator &first, + Iterator &last) { return channelsWithPrefix (prefix.c_str(), first, last); } @@ -292,14 +293,14 @@ ChannelList::channelsWithPrefix (const string &prefix, void ChannelList::channelsWithPrefix (const string &prefix, - ConstIterator &first, - ConstIterator &last) const + ConstIterator &first, + ConstIterator &last) const { return channelsWithPrefix (prefix.c_str(), first, last); } -bool +bool ChannelList::operator == (const ChannelList &other) const { ConstIterator i = begin(); @@ -307,15 +308,15 @@ ChannelList::operator == (const ChannelList &other) const while (i != end() && j != other.end()) { - if (!(i.channel() == j.channel())) - return false; + if (!(i.channel() == j.channel())) + return false; - ++i; - ++j; + ++i; + ++j; } return i == end() && j == other.end(); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfChannelList.h b/3rdparty/openexr/IlmImf/ImfChannelList.h index c29aba05fd..d36e7dc56e 100644 --- a/3rdparty/openexr/IlmImf/ImfChannelList.h +++ b/3rdparty/openexr/IlmImf/ImfChannelList.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,14 +44,17 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfName.h" +#include "ImfPixelType.h" + +#include "ImfNamespace.h" +#include "ImfExport.h" + #include #include #include - -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER struct Channel @@ -65,7 +68,7 @@ struct Channel //-------------------------------------------- // Subsampling: pixel (x, y) is present in the - // channel only if + // channel only if // // x % xSampling == 0 && y % ySampling == 0 // @@ -96,17 +99,19 @@ struct Channel //------------ // Constructor //------------ - + + IMF_EXPORT Channel (PixelType type = HALF, - int xSampling = 1, - int ySampling = 1, - bool pLinear = false); + int xSampling = 1, + int ySampling = 1, + bool pLinear = false); //------------ // Operator == //------------ + IMF_EXPORT bool operator == (const Channel &other) const; }; @@ -119,17 +124,19 @@ class ChannelList // Add a channel //-------------- + IMF_EXPORT void insert (const char name[], - const Channel &channel); + const Channel &channel); + IMF_EXPORT void insert (const std::string &name, - const Channel &channel); + const Channel &channel); //------------------------------------------------------------------ // Access to existing channels: // // [n] Returns a reference to the channel with name n. - // If no channel with name n exists, an Iex::ArgExc + // If no channel with name n exists, an IEX_NAMESPACE::ArgExc // is thrown. // // findChannel(n) Returns a pointer to the channel with name n, @@ -137,16 +144,24 @@ class ChannelList // //------------------------------------------------------------------ + IMF_EXPORT Channel & operator [] (const char name[]); + IMF_EXPORT const Channel & operator [] (const char name[]) const; + IMF_EXPORT Channel & operator [] (const std::string &name); + IMF_EXPORT const Channel & operator [] (const std::string &name) const; + IMF_EXPORT Channel * findChannel (const char name[]); + IMF_EXPORT const Channel * findChannel (const char name[]) const; + IMF_EXPORT Channel * findChannel (const std::string &name); + IMF_EXPORT const Channel * findChannel (const std::string &name) const; @@ -159,19 +174,27 @@ class ChannelList class Iterator; class ConstIterator; + IMF_EXPORT Iterator begin (); + IMF_EXPORT ConstIterator begin () const; + IMF_EXPORT Iterator end (); + IMF_EXPORT ConstIterator end () const; + IMF_EXPORT Iterator find (const char name[]); + IMF_EXPORT ConstIterator find (const char name[]) const; + IMF_EXPORT Iterator find (const std::string &name); + IMF_EXPORT ConstIterator find (const std::string &name) const; - + //----------------------------------------------------------------- // Support for image layers: // @@ -186,7 +209,7 @@ class ChannelList // several different virtual light sources. The channels in // this image might be called "light1.R", "light1.G", "light1.B", // "light2.R", "light2.G", "light2.B", etc. - // + // // Note that this naming convention allows layers to be nested; // for example, "light1.specular.R" identifies the "R" channel // in the "specular" sub-layer of layer "light1". @@ -212,15 +235,18 @@ class ChannelList // //----------------------------------------------------------------- + IMF_EXPORT void layers (std::set &layerNames) const; + IMF_EXPORT void channelsInLayer (const std::string &layerName, - Iterator &first, - Iterator &last); + Iterator &first, + Iterator &last); + IMF_EXPORT void channelsInLayer (const std::string &layerName, - ConstIterator &first, - ConstIterator &last) const; + ConstIterator &first, + ConstIterator &last) const; //------------------------------------------------------------------- @@ -235,26 +261,31 @@ class ChannelList // //------------------------------------------------------------------- + IMF_EXPORT void channelsWithPrefix (const char prefix[], - Iterator &first, - Iterator &last); + Iterator &first, + Iterator &last); + IMF_EXPORT void channelsWithPrefix (const char prefix[], - ConstIterator &first, - ConstIterator &last) const; + ConstIterator &first, + ConstIterator &last) const; + IMF_EXPORT void channelsWithPrefix (const std::string &prefix, - Iterator &first, - Iterator &last); + Iterator &first, + Iterator &last); + IMF_EXPORT void channelsWithPrefix (const std::string &prefix, - ConstIterator &first, - ConstIterator &last) const; + ConstIterator &first, + ConstIterator &last) const; //------------ // Operator == //------------ + IMF_EXPORT bool operator == (const ChannelList &other) const; private: @@ -271,13 +302,19 @@ class ChannelList::Iterator { public: + IMF_EXPORT Iterator (); + IMF_EXPORT Iterator (const ChannelList::ChannelMap::iterator &i); + IMF_EXPORT Iterator & operator ++ (); + IMF_EXPORT Iterator operator ++ (int); + IMF_EXPORT const char * name () const; + IMF_EXPORT Channel & channel () const; private: @@ -292,14 +329,21 @@ class ChannelList::ConstIterator { public: + IMF_EXPORT ConstIterator (); + IMF_EXPORT ConstIterator (const ChannelList::ChannelMap::const_iterator &i); + IMF_EXPORT ConstIterator (const ChannelList::Iterator &other); + IMF_EXPORT ConstIterator & operator ++ (); + IMF_EXPORT ConstIterator operator ++ (int); + IMF_EXPORT const char * name () const; + IMF_EXPORT const Channel & channel () const; private: @@ -330,7 +374,7 @@ ChannelList::Iterator::Iterator (const ChannelList::ChannelMap::iterator &i): } -inline ChannelList::Iterator & +inline ChannelList::Iterator & ChannelList::Iterator::operator ++ () { ++_i; @@ -338,7 +382,7 @@ ChannelList::Iterator::operator ++ () } -inline ChannelList::Iterator +inline ChannelList::Iterator ChannelList::Iterator::operator ++ (int) { Iterator tmp = *this; @@ -354,7 +398,7 @@ ChannelList::Iterator::name () const } -inline Channel & +inline Channel & ChannelList::Iterator::channel () const { return _i->second; @@ -390,7 +434,7 @@ ChannelList::ConstIterator::operator ++ () } -inline ChannelList::ConstIterator +inline ChannelList::ConstIterator ChannelList::ConstIterator::operator ++ (int) { ConstIterator tmp = *this; @@ -405,7 +449,7 @@ ChannelList::ConstIterator::name () const return *_i->first; } -inline const Channel & +inline const Channel & ChannelList::ConstIterator::channel () const { return _i->second; @@ -414,7 +458,7 @@ ChannelList::ConstIterator::channel () const inline bool operator == (const ChannelList::ConstIterator &x, - const ChannelList::ConstIterator &y) + const ChannelList::ConstIterator &y) { return x._i == y._i; } @@ -422,12 +466,12 @@ operator == (const ChannelList::ConstIterator &x, inline bool operator != (const ChannelList::ConstIterator &x, - const ChannelList::ConstIterator &y) + const ChannelList::ConstIterator &y) { return !(x == y); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfChannelListAttribute.cpp b/3rdparty/openexr/IlmImf/ImfChannelListAttribute.cpp index f4ab3e301a..5549493097 100644 --- a/3rdparty/openexr/IlmImf/ImfChannelListAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfChannelListAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,26 +42,26 @@ #include - -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER namespace { template void checkIsNullTerminated (const char (&str)[N], const char *what) { - for (int i = 0; i < N; ++i) { + for (size_t i = 0; i < N; ++i) { if (str[i] == '\0') return; } std::stringstream s; - s << "Invalid " << what << ": it is more than " << (N - 1) + s << "Invalid " << what << ": it is more than " << (N - 1) << " characters long."; - throw Iex::InputExc(s); + throw IEX_NAMESPACE::InputExc(s); } } // namespace + template <> const char * ChannelListAttribute::staticTypeName () @@ -69,30 +69,31 @@ ChannelListAttribute::staticTypeName () return "chlist"; } +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> void -ChannelListAttribute::writeValueTo (OStream &os, int) const +ChannelListAttribute::writeValueTo (OStream &os, int version) const { for (ChannelList::ConstIterator i = _value.begin(); - i != _value.end(); - ++i) + i != _value.end(); + ++i) { - // - // Write name - // + // + // Write name + // - Xdr::write (os, i.name()); + Xdr::write (os, i.name()); - // - // Write Channel struct - // + // + // Write Channel struct + // - Xdr::write (os, int (i.channel().type)); - Xdr::write (os, i.channel().pLinear); - Xdr::pad (os, 3); - Xdr::write (os, i.channel().xSampling); - Xdr::write (os, i.channel().ySampling); + Xdr::write (os, int (i.channel().type)); + Xdr::write (os, i.channel().pLinear); + Xdr::pad (os, 3); + Xdr::write (os, i.channel().xSampling); + Xdr::write (os, i.channel().ySampling); } // @@ -105,41 +106,45 @@ ChannelListAttribute::writeValueTo (OStream &os, int) const template <> void -ChannelListAttribute::readValueFrom (IStream &is, int, int) +ChannelListAttribute::readValueFrom (IStream &is, + int size, + int version) { while (true) { - // - // Read name; zero length name means end of channel list - // + // + // Read name; zero length name means end of channel list + // - char name[Name::SIZE]; - Xdr::read (is, Name::MAX_LENGTH, name); + char name[Name::SIZE]; + Xdr::read (is,Name::MAX_LENGTH,name); - if (name[0] == 0) - break; + if (name[0] == 0) + break; - checkIsNullTerminated (name, "channel name"); + checkIsNullTerminated (name, "channel name"); - // - // Read Channel struct - // + // + // Read Channel struct + // - int type; - bool pLinear; - int xSampling; - int ySampling; + int type; + bool pLinear; + int xSampling; + int ySampling; - Xdr::read (is, type); - Xdr::read (is, pLinear); - Xdr::skip (is, 3); - Xdr::read (is, xSampling); - Xdr::read (is, ySampling); + Xdr::read (is, type); + Xdr::read (is, pLinear); + Xdr::skip (is, 3); + Xdr::read (is, xSampling); + Xdr::read (is, ySampling); - _value.insert - (name, Channel (PixelType (type), xSampling, ySampling, pLinear)); + _value.insert (name, Channel (PixelType (type), + xSampling, + ySampling, + pLinear)); } } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfChannelListAttribute.h b/3rdparty/openexr/IlmImf/ImfChannelListAttribute.h index d45832b5c0..60d89078c2 100644 --- a/3rdparty/openexr/IlmImf/ImfChannelListAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfChannelListAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,25 +43,32 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfChannelList.h" +#include "ImfExport.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { +typedef TypedAttribute ChannelListAttribute; -typedef TypedAttribute ChannelListAttribute; -template <> const char *ChannelListAttribute::staticTypeName (); -template <> void ChannelListAttribute::writeValueTo (OStream &, int) const; -template <> void ChannelListAttribute::readValueFrom (IStream &, int, int); +template <> +IMF_EXPORT +const char *ChannelListAttribute::staticTypeName (); +template <> +IMF_EXPORT +void ChannelListAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; -} // namespace Imf +template <> +IMF_EXPORT +void ChannelListAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif #endif diff --git a/3rdparty/openexr/IlmImf/ImfCheckedArithmetic.h b/3rdparty/openexr/IlmImf/ImfCheckedArithmetic.h index c0a81ee7d3..6a7fc15283 100644 --- a/3rdparty/openexr/IlmImf/ImfCheckedArithmetic.h +++ b/3rdparty/openexr/IlmImf/ImfCheckedArithmetic.h @@ -2,9 +2,9 @@ // // Copyright (c) 2009, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,15 +43,16 @@ //----------------------------------------------------------------------------- #include -#include +#include "IexMathExc.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER template struct StaticAssertionFailed; template <> struct StaticAssertionFailed {}; #define IMF_STATIC_ASSERT(x) \ - do {StaticAssertionFailed staticAssertionFailed;} while (false) + do {StaticAssertionFailed staticAssertionFailed; ((void) staticAssertionFailed);} while (false) template @@ -66,7 +67,7 @@ uiMult (T a, T b) std::numeric_limits::is_integer); if (a > 0 && b > std::numeric_limits::max() / a) - throw Iex::OverflowExc ("Integer multiplication overflow."); + throw IEX_NAMESPACE::OverflowExc ("Integer multiplication overflow."); return a * b; } @@ -84,7 +85,7 @@ uiDiv (T a, T b) std::numeric_limits::is_integer); if (b == 0) - throw Iex::DivzeroExc ("Integer division by zero."); + throw IEX_NAMESPACE::DivzeroExc ("Integer division by zero."); return a / b; } @@ -102,7 +103,7 @@ uiAdd (T a, T b) std::numeric_limits::is_integer); if (a > std::numeric_limits::max() - b) - throw Iex::OverflowExc ("Integer addition overflow."); + throw IEX_NAMESPACE::OverflowExc ("Integer addition overflow."); return a + b; } @@ -120,7 +121,7 @@ uiSub (T a, T b) std::numeric_limits::is_integer); if (a < b) - throw Iex::UnderflowExc ("Integer subtraction underflow."); + throw IEX_NAMESPACE::UnderflowExc ("Integer subtraction underflow."); return a - b; } @@ -138,7 +139,7 @@ checkArraySize (T n, size_t s) // // size_t (n) * s // - // would overflow, then throw an Iex::OverflowExc exception. + // would overflow, then throw an IEX_NAMESPACE::OverflowExc exception. // Otherwise return // // size_t (n). @@ -150,12 +151,13 @@ checkArraySize (T n, size_t s) IMF_STATIC_ASSERT (sizeof (T) <= sizeof (size_t)); if (size_t (n) > std::numeric_limits::max() / s) - throw Iex::OverflowExc ("Integer multiplication overflow."); + throw IEX_NAMESPACE::OverflowExc ("Integer multiplication overflow."); return size_t (n); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + #endif diff --git a/3rdparty/openexr/IlmImf/ImfChromaticities.cpp b/3rdparty/openexr/IlmImf/ImfChromaticities.cpp index 4368f03d38..f354cdfe5a 100644 --- a/3rdparty/openexr/IlmImf/ImfChromaticities.cpp +++ b/3rdparty/openexr/IlmImf/ImfChromaticities.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2003, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,14 +41,16 @@ //----------------------------------------------------------------------------- #include +#include "ImfNamespace.h" +#include -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -Chromaticities::Chromaticities (const Imath::V2f &red, - const Imath::V2f &green, - const Imath::V2f &blue, - const Imath::V2f &white) + +Chromaticities::Chromaticities (const IMATH_NAMESPACE::V2f &red, + const IMATH_NAMESPACE::V2f &green, + const IMATH_NAMESPACE::V2f &blue, + const IMATH_NAMESPACE::V2f &white) : red (red), green (green), @@ -58,14 +60,28 @@ Chromaticities::Chromaticities (const Imath::V2f &red, // empty } + +bool +Chromaticities::operator == (const Chromaticities & c) const +{ + return red == c.red && green == c.green && blue == c.blue; +} -Imath::M44f + +bool +Chromaticities::operator != (const Chromaticities & c) const +{ + return red != c.red || green != c.green || blue != c.blue; +} + + +IMATH_NAMESPACE::M44f RGBtoXYZ (const Chromaticities chroma, float Y) { // // For an explanation of how the color conversion matrix is derived, // see Roy Hall, "Illumination and Color in Computer Generated Imagery", - // Springer-Verlag, 1989, chapter 3, "Perceptual Response"; and + // Springer-Verlag, 1989, chapter 3, "Perceptual Response"; and // Charles A. Poynton, "A Technical Introduction to Digital Video", // John Wiley & Sons, 1996, chapter 7, "Color science for video". // @@ -82,32 +98,32 @@ RGBtoXYZ (const Chromaticities chroma, float Y) // float d = chroma.red.x * (chroma.blue.y - chroma.green.y) + - chroma.blue.x * (chroma.green.y - chroma.red.y) + - chroma.green.x * (chroma.red.y - chroma.blue.y); + chroma.blue.x * (chroma.green.y - chroma.red.y) + + chroma.green.x * (chroma.red.y - chroma.blue.y); float Sr = (X * (chroma.blue.y - chroma.green.y) - - chroma.green.x * (Y * (chroma.blue.y - 1) + - chroma.blue.y * (X + Z)) + - chroma.blue.x * (Y * (chroma.green.y - 1) + - chroma.green.y * (X + Z))) / d; + chroma.green.x * (Y * (chroma.blue.y - 1) + + chroma.blue.y * (X + Z)) + + chroma.blue.x * (Y * (chroma.green.y - 1) + + chroma.green.y * (X + Z))) / d; float Sg = (X * (chroma.red.y - chroma.blue.y) + - chroma.red.x * (Y * (chroma.blue.y - 1) + - chroma.blue.y * (X + Z)) - - chroma.blue.x * (Y * (chroma.red.y - 1) + - chroma.red.y * (X + Z))) / d; + chroma.red.x * (Y * (chroma.blue.y - 1) + + chroma.blue.y * (X + Z)) - + chroma.blue.x * (Y * (chroma.red.y - 1) + + chroma.red.y * (X + Z))) / d; float Sb = (X * (chroma.green.y - chroma.red.y) - - chroma.red.x * (Y * (chroma.green.y - 1) + - chroma.green.y * (X + Z)) + - chroma.green.x * (Y * (chroma.red.y - 1) + - chroma.red.y * (X + Z))) / d; + chroma.red.x * (Y * (chroma.green.y - 1) + + chroma.green.y * (X + Z)) + + chroma.green.x * (Y * (chroma.red.y - 1) + + chroma.red.y * (X + Z))) / d; // // Assemble the matrix // - Imath::M44f M; + IMATH_NAMESPACE::M44f M; M[0][0] = Sr * chroma.red.x; M[0][1] = Sr * chroma.red.y; @@ -125,11 +141,11 @@ RGBtoXYZ (const Chromaticities chroma, float Y) } -Imath::M44f +IMATH_NAMESPACE::M44f XYZtoRGB (const Chromaticities chroma, float Y) { return RGBtoXYZ (chroma, Y).inverse(); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfChromaticities.h b/3rdparty/openexr/IlmImf/ImfChromaticities.h index 28614c0b9a..96b09284e3 100644 --- a/3rdparty/openexr/IlmImf/ImfChromaticities.h +++ b/3rdparty/openexr/IlmImf/ImfChromaticities.h @@ -2,9 +2,9 @@ // // Copyright (c) 2003, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,10 +45,13 @@ #include "ImathVec.h" #include "ImathMatrix.h" +#include "ImfNamespace.h" +#include "ImfExport.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + struct Chromaticities { //----------------------------------------------- @@ -56,20 +59,31 @@ struct Chromaticities // (1,0,0), (0,1,0), (0,0,1) and (1,1,1). //----------------------------------------------- - Imath::V2f red; - Imath::V2f green; - Imath::V2f blue; - Imath::V2f white; + IMATH_NAMESPACE::V2f red; + IMATH_NAMESPACE::V2f green; + IMATH_NAMESPACE::V2f blue; + IMATH_NAMESPACE::V2f white; //-------------------------------------------- // Default constructor produces chromaticities // according to Rec. ITU-R BT.709-3 //-------------------------------------------- - Chromaticities (const Imath::V2f &red = Imath::V2f (0.6400f, 0.3300f), - const Imath::V2f &green = Imath::V2f (0.3000f, 0.6000f), - const Imath::V2f &blue = Imath::V2f (0.1500f, 0.0600f), - const Imath::V2f &white = Imath::V2f (0.3127f, 0.3290f)); + IMF_EXPORT + Chromaticities (const IMATH_NAMESPACE::V2f &red = IMATH_NAMESPACE::V2f (0.6400f, 0.3300f), + const IMATH_NAMESPACE::V2f &green = IMATH_NAMESPACE::V2f (0.3000f, 0.6000f), + const IMATH_NAMESPACE::V2f &blue = IMATH_NAMESPACE::V2f (0.1500f, 0.0600f), + const IMATH_NAMESPACE::V2f &white = IMATH_NAMESPACE::V2f (0.3127f, 0.3290f)); + + + //--------- + // Equality + //--------- + + IMF_EXPORT + bool operator == (const Chromaticities &v) const; + IMF_EXPORT + bool operator != (const Chromaticities &v) const; }; @@ -82,39 +96,39 @@ struct Chromaticities // triple (1,1,1), or "white", RGBtoXYZ(c,Y) computes a matrix, M, so // that multiplying an RGB value, v, with M produces an equivalent // XYZ value, w. (w == v * M) -// +// // If we define that -// +// // (Xr, Yr, Zr) == (1, 0, 0) * M // (Xg, Yg, Zg) == (0, 1, 0) * M // (Xb, Yb, Zb) == (0, 0, 1) * M // (Xw, Yw, Zw) == (1, 1, 1) * M, -// +// // then the following statements are true: -// +// // Xr / (Xr + Yr + Zr) == c.red.x // Yr / (Xr + Yr + Zr) == c.red.y -// +// // Xg / (Xg + Yg + Zg) == c.red.x // Yg / (Xg + Yg + Zg) == c.red.y -// +// // Xb / (Xb + Yb + Zb) == c.red.x // Yb / (Xb + Yb + Zb) == c.red.y -// +// // Xw / (Xw + Yw + Zw) == c.red.x // Yw / (Xw + Yw + Zw) == c.red.y -// +// // Yw == Y. -// +// // XYZ to RGB: -// +// // YYZtoRGB(c,Y) returns RGBtoXYZ(c,Y).inverse(). -// +// -Imath::M44f RGBtoXYZ (const Chromaticities chroma, float Y); -Imath::M44f XYZtoRGB (const Chromaticities chroma, float Y); +IMF_EXPORT IMATH_NAMESPACE::M44f RGBtoXYZ (const Chromaticities chroma, float Y); +IMF_EXPORT IMATH_NAMESPACE::M44f XYZtoRGB (const Chromaticities chroma, float Y); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfChromaticitiesAttribute.cpp b/3rdparty/openexr/IlmImf/ImfChromaticitiesAttribute.cpp index ba8fb331be..4d7b985c3f 100644 --- a/3rdparty/openexr/IlmImf/ImfChromaticitiesAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfChromaticitiesAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2003, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,8 +42,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -55,7 +56,7 @@ ChromaticitiesAttribute::staticTypeName () template <> void -ChromaticitiesAttribute::writeValueTo (OStream &os, int) const +ChromaticitiesAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.red.x); Xdr::write (os, _value.red.y); @@ -70,7 +71,7 @@ ChromaticitiesAttribute::writeValueTo (OStream &os, int) const template <> void -ChromaticitiesAttribute::readValueFrom (IStream &is, int, int) +ChromaticitiesAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.red.x); Xdr::read (is, _value.red.y); @@ -83,4 +84,4 @@ ChromaticitiesAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfChromaticitiesAttribute.h b/3rdparty/openexr/IlmImf/ImfChromaticitiesAttribute.h index ed2f47852d..6c0c35ac7a 100644 --- a/3rdparty/openexr/IlmImf/ImfChromaticitiesAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfChromaticitiesAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2003, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,30 +43,31 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfChromaticities.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { - -typedef TypedAttribute ChromaticitiesAttribute; +typedef TypedAttribute ChromaticitiesAttribute; template <> +IMF_EXPORT const char *ChromaticitiesAttribute::staticTypeName (); template <> -void ChromaticitiesAttribute::writeValueTo (OStream &, int) const; +IMF_EXPORT +void ChromaticitiesAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; template <> -void ChromaticitiesAttribute::readValueFrom (IStream &, int, int); +IMF_EXPORT +void ChromaticitiesAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, + int); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif #endif diff --git a/3rdparty/openexr/IlmImf/ImfCompositeDeepScanLine.cpp b/3rdparty/openexr/IlmImf/ImfCompositeDeepScanLine.cpp new file mode 100644 index 0000000000..7e0dac098c --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfCompositeDeepScanLine.cpp @@ -0,0 +1,591 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Weta Digital Ltd +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Weta Digital nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#include "ImfCompositeDeepScanLine.h" +#include "ImfDeepScanLineInputPart.h" +#include "ImfDeepScanLineInputFile.h" +#include "ImfChannelList.h" +#include "ImfFrameBuffer.h" +#include "ImfDeepFrameBuffer.h" +#include "ImfDeepCompositing.h" +#include "ImfPixelType.h" +#include "IlmThreadPool.h" + +#include +#include +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using std::vector; +using std::string; +using IMATH_NAMESPACE::Box2i; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; + + + +struct CompositeDeepScanLine::Data{ + public : + vector _file; // array of files + vector _part; // array of parts + FrameBuffer _outputFrameBuffer; // output frame buffer provided + bool _zback; // true if we are using zback (otherwise channel 1 = channel 0) + vector< vector > _channeldata; // pixel values, read from the input, one array per channel + vector< int > _sampleCounts; // total per-pixel sample counts, + Box2i _dataWindow; // data window of combined inputs + DeepCompositing * _comp; // user-provided compositor + vector _channels; // names of channels that will be composited + vector _bufferMap; // entry _outputFrameBuffer[n].name() == _channels[ _bufferMap[n] ].name() + + void check_valid(const Header & header); // check newly added part/file is OK; on first good call, set _zback/_dataWindow + + // + // set up the given deep frame buffer to contain the required channels + // resize counts and pointers to the width of _dataWindow + // zero-out all counts, since the datawindow may be smaller than/not include this part + // + + void handleDeepFrameBuffer (DeepFrameBuffer & buf, + vector & counts, //per-pixel counts + vector< vector > & pointers, //per-channel-per-pixel pointers to data + const Header & header, + int start, + int end); + + Data(); +}; + +CompositeDeepScanLine::Data::Data() : _zback(false) , _comp(NULL) {} + +CompositeDeepScanLine::CompositeDeepScanLine() : _Data(new Data) {} + +CompositeDeepScanLine::~CompositeDeepScanLine() +{ + delete _Data; +} + +void +CompositeDeepScanLine::addSource(DeepScanLineInputPart* part) +{ + _Data->check_valid(part->header()); + _Data->_part.push_back(part); +} + +void +CompositeDeepScanLine::addSource(DeepScanLineInputFile* file) +{ + _Data->check_valid(file->header()); + _Data->_file.push_back(file); +} + +int +CompositeDeepScanLine::sources() const +{ + return int(_Data->_part.size())+int(_Data->_file.size()); +} + +void +CompositeDeepScanLine::Data::check_valid(const Header & header) +{ + + bool has_z=false; + bool has_alpha=false; + // check good channel names + for( ChannelList::ConstIterator i=header.channels().begin();i!=header.channels().end();++i) + { + std::string n(i.name()); + if(n=="ZBack") + { + _zback=true; + } + else if(n=="Z") + { + has_z=true; + } + else if(n=="A") + { + has_alpha=true; + } + } + + if(!has_z) + { + throw IEX_NAMESPACE::ArgExc("Deep data provided to CompositeDeepScanLine is missing a Z channel"); + } + + if(!has_alpha) + { + throw IEX_NAMESPACE::ArgExc("Deep data provided to CompositeDeepScanLine is missing an alpha channel"); + } + + + if(_part.size()==0 && _file.size()==0) + { + // first in - update and return + + _dataWindow = header.dataWindow(); + + return; + } + + + const Header * const match_header = _part.size()>0 ? &_part[0]->header() : &_file[0]->header(); + + // check the sizes match + if(match_header->displayWindow() != header.displayWindow()) + { + throw IEX_NAMESPACE::ArgExc("Deep data provided to CompositeDeepScanLine has a different displayWindow to previously provided data"); + } + + _dataWindow.extendBy(header.dataWindow()); + +} +void +CompositeDeepScanLine::Data::handleDeepFrameBuffer (DeepFrameBuffer& buf, + std::vector< unsigned int > & counts, + vector< std::vector< float* > > & pointers, + const Header& header, + int start, + int end) +{ + int width=_dataWindow.size().x+1; + size_t pixelcount = width * (end-start+1); + pointers.resize(_channels.size()); + counts.resize(pixelcount); + buf.insertSampleCountSlice (Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::UINT, + (char *) (&counts[0]-_dataWindow.min.x-start*width), + sizeof(unsigned int), + sizeof(unsigned int)*width)); + + pointers[0].resize(pixelcount); + buf.insert ("Z", DeepSlice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT, + (char *)(&pointers[0][0]-_dataWindow.min.x-start*width), + sizeof(float *), + sizeof(float *)*width, + sizeof(float) )); + + if(_zback) + { + pointers[1].resize(pixelcount); + buf.insert ("ZBack", DeepSlice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT, + (char *)(&pointers[1][0]-_dataWindow.min.x-start*width), + sizeof(float *), + sizeof(float *)*width, + sizeof(float) )); + } + + pointers[2].resize(pixelcount); + buf.insert ("A", DeepSlice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT, + (char *)(&pointers[2][0]-_dataWindow.min.x-start*width), + sizeof(float *), + sizeof(float *)*width, + sizeof(float) )); + + + size_t i =0; + for(FrameBuffer::ConstIterator qt = _outputFrameBuffer.begin(); + qt != _outputFrameBuffer.end(); + qt++) + { + int channel_in_source = _bufferMap[i]; + if(channel_in_source>2) + { + // not dealt with yet (0,1,2 previously inserted) + pointers[channel_in_source].resize(pixelcount); + buf.insert (qt.name(), + DeepSlice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT, + (char *)(&pointers[channel_in_source][0]-_dataWindow.min.x-start*width), + sizeof(float *), + sizeof(float *)*width, + sizeof(float) )); + } + + i++; + } + +} + +void +CompositeDeepScanLine::setCompositing(DeepCompositing* c) +{ + _Data->_comp=c; +} + +const IMATH_NAMESPACE::Box2i& CompositeDeepScanLine::dataWindow() const +{ + return _Data->_dataWindow; +} + + +void +CompositeDeepScanLine::setFrameBuffer(const FrameBuffer& fr) +{ + + // + // count channels; build map between channels in frame buffer + // and channels in internal buffers + // + + _Data->_channels.resize(3); + _Data->_channels[0]="Z"; + _Data->_channels[1]=_Data->_zback ? "ZBack" : "Z"; + _Data->_channels[2]="A"; + _Data->_bufferMap.resize(0); + + for(FrameBuffer::ConstIterator q=fr.begin();q!=fr.end();q++) + { + string name(q.name()); + if(name=="ZBack") + { + _Data->_bufferMap.push_back(1); + }else if(name=="Z") + { + _Data->_bufferMap.push_back(0); + }else if(name=="A") + { + _Data->_bufferMap.push_back(2); + }else{ + _Data->_bufferMap.push_back(_Data->_channels.size()); + _Data->_channels.push_back(name); + } + } + + _Data->_outputFrameBuffer=fr; +} + +namespace +{ + +class LineCompositeTask : public Task +{ + public: + + LineCompositeTask ( TaskGroup* group , + CompositeDeepScanLine::Data * data, + int y, + int start, + vector* names, + vector > >* pointers, + vector* total_sizes, + vector* num_sources + ) : Task(group) , + _Data(data), + _y(y), + _start(start), + _names(names), + _pointers(pointers), + _total_sizes(total_sizes), + _num_sources(num_sources) + {} + + virtual ~LineCompositeTask () {} + + virtual void execute (); + CompositeDeepScanLine::Data* _Data; + int _y; + int _start; + vector* _names; + vector > >* _pointers; + vector* _total_sizes; + vector* _num_sources; + +}; + + +void +composite_line(int y, + int start, + CompositeDeepScanLine::Data * _Data, + vector & names, + const vector > > & pointers, + const vector & total_sizes, + const vector & num_sources + ) +{ + vector output_pixel(names.size()); //the pixel we'll output to + vector inputs(names.size()); + DeepCompositing d; // fallback compositing engine + DeepCompositing * comp= _Data->_comp ? _Data->_comp : &d; + + int pixel = (y-start)*(_Data->_dataWindow.max.x+1-_Data->_dataWindow.min.x); + + for(int x=_Data->_dataWindow.min.x;x<=_Data->_dataWindow.max.x;x++) + { + // set inputs[] to point to the first sample of the first part of each channel + // if there's a zback, set all channel independently... + + if(_Data->_zback) + { + + for(size_t channel=0;channelcomposite_pixel(&output_pixel[0], + &inputs[0], + &names[0], + names.size(), + total_sizes[pixel], + num_sources[pixel] + ); + + + size_t channel_number=0; + + + // + // write out composited value into internal frame buffer + // + for(FrameBuffer::Iterator it = _Data->_outputFrameBuffer.begin();it !=_Data->_outputFrameBuffer.end();it++) + { + + float value = output_pixel[ _Data->_bufferMap[channel_number] ]; // value to write + + + // cast to half float if necessary + if(it.slice().type==OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT) + { + * (float *)(it.slice().base + y*it.slice().yStride + x*it.slice().xStride) = value; + } + else if(it.slice().type==HALF) + { + * (half *)(it.slice().base + y*it.slice().yStride + x*it.slice().xStride) = half(value); + } + + channel_number++; + + } + + pixel++; + + }// next pixel on row +} + +void LineCompositeTask::execute() +{ + composite_line(_y,_start,_Data,*_names,*_pointers,*_total_sizes,*_num_sources); +} + + +} + +void +CompositeDeepScanLine::readPixels(int start, int end) +{ + size_t parts = _Data->_file.size() + _Data->_part.size(); // total of files+parts + + vector framebuffers(parts); + vector< vector > counts(parts); + + // + // for each part, a pointer to an array of channels + // + vector > > pointers(parts); + vector headers(parts); + + { + size_t i; + for(i=0;i<_Data->_file.size();i++) + { + headers[i] = &_Data->_file[i]->header(); + } + + for(size_t j=0;j<_Data->_part.size();j++) + { + headers[i+j] = &_Data->_part[j]->header(); + } + } + + + for(size_t i=0;ihandleDeepFrameBuffer(framebuffers[i],counts[i],pointers[i],*headers[i],start,end); + } + + // + // set frame buffers and read scanlines from all parts + // TODO what happens if SCANLINE not in data window? + // + + { + size_t i=0; + for(i=0;i<_Data->_file.size();i++) + { + _Data->_file[i]->setFrameBuffer(framebuffers[i]); + _Data->_file[i]->readPixelSampleCounts(start,end); + } + for(size_t j=0;j<_Data->_part.size();j++) + { + _Data->_part[j]->setFrameBuffer(framebuffers[i+j]); + _Data->_part[j]->readPixelSampleCounts(start,end); + } + } + + + // + // total width + // + + size_t total_width = _Data->_dataWindow.size().x+1; + size_t total_pixels = total_width*(end-start+1); + vector total_sizes(total_pixels); + vector num_sources(total_pixels); //number of parts with non-zero sample count + + size_t overall_sample_count=0; // sum of all samples in all images between start and end + + + // + // accumulate pixel counts + // + for(size_t ptr=0;ptr0) num_sources[ptr]++; + } + overall_sample_count+=total_sizes[ptr]; + + + + } + + + + + // + // allocate arrays for pixel data + // samples array accessed as in pixels[channel][sample] + // + + vector > samples( _Data->_channels.size() ); + + for(size_t channel=0;channel<_Data->_channels.size();channel++) + { + if( channel!=1 || _Data->_zback) + { + samples[channel].resize(overall_sample_count); + } + } + + for(size_t channel=0;channel_zback) + { + + samples[channel].resize(overall_sample_count); + + + // + // allocate pointers for channel data + // + + size_t offset=0; + + for(size_t pixel=0;pixel_file.size();i++) + { + _Data->_file[i]->readPixels(start,end); + } + for(size_t j=0;j<_Data->_part.size();j++) + { + _Data->_part[j]->readPixels(start,end); + } + + + + + // + // composite pixels and write back to framebuffer + // + + + // turn vector of strings into array of char * + // and make sure 'ZBack' channel is correct + vector names(_Data->_channels.size()); + for(size_t i=0;i_channels[i].c_str(); + } + + if(!_Data->_zback) names[1]=names[0]; // no zback channel, so make it point to z + + + + TaskGroup g; + for(int y=start;y<=end;y++) + { + ThreadPool::addGlobalTask(new LineCompositeTask(&g,_Data,y,start,&names,&pointers,&total_sizes,&num_sources)); + }//next row +} + +const FrameBuffer& +CompositeDeepScanLine::frameBuffer() const +{ + return _Data->_outputFrameBuffer; +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfCompositeDeepScanLine.h b/3rdparty/openexr/IlmImf/ImfCompositeDeepScanLine.h new file mode 100644 index 0000000000..13c3fbe220 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfCompositeDeepScanLine.h @@ -0,0 +1,152 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Weta Digital Ltd +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Weta Digital nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#ifndef INCLUDED_IMF_COMPOSITEDEEPSCANLINE_H +#define INCLUDED_IMF_COMPOSITEDEEPSCANLINE_H + +//----------------------------------------------------------------------------- +// +// Class to composite deep samples into a frame buffer +// Initialise with a deep input part or deep inputfile +// (also supports multiple files and parts, and will +// composite them together, as long as their sizes and channelmaps agree) +// +// Then call setFrameBuffer, and readPixels, exactly as for reading +// regular scanline images. +// +// Restrictions - source file(s) must contain at least Z and alpha channels +// - if multiple files/parts are provided, sizes must match +// - all requested channels will be composited as premultiplied +// - only half and float channels can be requested +// +// This object should not be considered threadsafe +// +// The default compositing engine will give spurious results with overlapping +// volumetric samples - you may derive from DeepCompositing class, override the +// sort_pixel() and composite_pixel() functions, and pass an instance to +// setCompositing(). +// +//----------------------------------------------------------------------------- + +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class CompositeDeepScanLine +{ + public: + IMF_EXPORT + CompositeDeepScanLine(); + IMF_EXPORT + virtual ~CompositeDeepScanLine(); + + /// set the source data as a part + ///@note all parts must remain valid until after last interaction with DeepComp + IMF_EXPORT + void addSource(DeepScanLineInputPart * part); + + /// set the source data as a file + ///@note all file must remain valid until after last interaction with DeepComp + IMF_EXPORT + void addSource(DeepScanLineInputFile * file); + + + ///////////////////////////////////////// + // + // set the frame buffer for output values + // the buffers specified must be large enough + // to handle the dataWindow() + // + ///////////////////////////////////////// + IMF_EXPORT + void setFrameBuffer(const FrameBuffer & fr); + + + + ///////////////////////////////////////// + // + // retrieve frameBuffer + // + //////////////////////////////////////// + IMF_EXPORT + const FrameBuffer & frameBuffer() const; + + + ////////////////////////////////////////////////// + // + // read scanlines start to end from the source(s) + // storing the result in the frame buffer provided + // + ////////////////////////////////////////////////// + + IMF_EXPORT + void readPixels(int start,int end); + + IMF_EXPORT + int sources() const; // return number of sources + + ///////////////////////////////////////////////// + // + // retrieve the datawindow + // If multiple parts are specified, this will + // be the union of the dataWindow of all parts + // + //////////////////////////////////////////////// + + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & dataWindow() const; + + + // + // override default sorting/compositing operation + // (otherwise an instance of the base class will be used) + // + + IMF_EXPORT + void setCompositing(DeepCompositing *); + + struct Data; + private : + struct Data *_Data; + + CompositeDeepScanLine(const CompositeDeepScanLine &); // not implemented + const CompositeDeepScanLine & operator=(const CompositeDeepScanLine &); // not implemented +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfCompression.h b/3rdparty/openexr/IlmImf/ImfCompression.h index ed1e4ff52e..c066d34c88 100644 --- a/3rdparty/openexr/IlmImf/ImfCompression.h +++ b/3rdparty/openexr/IlmImf/ImfCompression.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,9 +42,9 @@ // enum Compression // //----------------------------------------------------------------------------- +#include "ImfNamespace.h" -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER enum Compression { @@ -61,15 +61,24 @@ enum Compression PXR24_COMPRESSION = 5, // lossy 24-bit float compression B44_COMPRESSION = 6, // lossy 4-by-4 pixel block compression, - // fixed compression rate + // fixed compression rate B44A_COMPRESSION = 7, // lossy 4-by-4 pixel block compression, - // flat fields are compressed more + // flat fields are compressed more + + DWAA_COMPRESSION = 8, // lossy DCT based compression, in blocks + // of 32 scanlines. More efficient for partial + // buffer access. + + DWAB_COMPRESSION = 9, // lossy DCT based compression, in blocks + // of 256 scanlines. More efficient space + // wise and faster to decode full frames + // than DWAA_COMPRESSION. NUM_COMPRESSION_METHODS // number of different compression methods }; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imf #endif diff --git a/3rdparty/openexr/IlmImf/ImfCompressionAttribute.cpp b/3rdparty/openexr/IlmImf/ImfCompressionAttribute.cpp index c198613428..a32c689358 100644 --- a/3rdparty/openexr/IlmImf/ImfCompressionAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfCompressionAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -40,10 +40,12 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfCompressionAttribute.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> @@ -56,7 +58,7 @@ CompressionAttribute::staticTypeName () template <> void -CompressionAttribute::writeValueTo (OStream &os, int) const +CompressionAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { unsigned char tmp = _value; Xdr::write (os, tmp); @@ -65,7 +67,7 @@ CompressionAttribute::writeValueTo (OStream &os, int) const template <> void -CompressionAttribute::readValueFrom (IStream &is, int, int) +CompressionAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { unsigned char tmp; Xdr::read (is, tmp); @@ -73,4 +75,4 @@ CompressionAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfCompressionAttribute.h b/3rdparty/openexr/IlmImf/ImfCompressionAttribute.h index be83f2c0c7..eea95dd602 100644 --- a/3rdparty/openexr/IlmImf/ImfCompressionAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfCompressionAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,24 +43,22 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfCompression.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { +typedef TypedAttribute CompressionAttribute; +template <> IMF_EXPORT const char *CompressionAttribute::staticTypeName (); +template <> IMF_EXPORT void CompressionAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; +template <> IMF_EXPORT void CompressionAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, + int); -typedef TypedAttribute CompressionAttribute; -template <> const char *CompressionAttribute::staticTypeName (); -template <> void CompressionAttribute::writeValueTo (OStream &, int) const; -template <> void CompressionAttribute::readValueFrom (IStream &, int, int); +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imf - -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif #endif diff --git a/3rdparty/openexr/IlmImf/ImfCompressor.cpp b/3rdparty/openexr/IlmImf/ImfCompressor.cpp index fc5beaf98a..1905a4d66b 100644 --- a/3rdparty/openexr/IlmImf/ImfCompressor.cpp +++ b/3rdparty/openexr/IlmImf/ImfCompressor.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -40,17 +40,19 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include +#include "ImfCompressor.h" +#include "ImfRleCompressor.h" +#include "ImfZipCompressor.h" +#include "ImfPizCompressor.h" +#include "ImfPxr24Compressor.h" +#include "ImfB44Compressor.h" +#include "ImfDwaCompressor.h" +#include "ImfCheckedArithmetic.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -using Imath::Box2i; +using IMATH_NAMESPACE::Box2i; Compressor::Compressor (const Header &hdr): _header (hdr) {} @@ -68,25 +70,25 @@ Compressor::format () const int Compressor::compressTile (const char *inPtr, - int inSize, - Box2i range, - const char *&outPtr) + int inSize, + Box2i range, + const char *&outPtr) { return compress (inPtr, inSize, range.min.y, outPtr); } - + int Compressor::uncompressTile (const char *inPtr, - int inSize, - Box2i range, - const char *&outPtr) + int inSize, + Box2i range, + const char *&outPtr) { return uncompress (inPtr, inSize, range.min.y, outPtr); } -bool +bool isValidCompression (Compression c) { switch (c) @@ -99,15 +101,30 @@ isValidCompression (Compression c) case PXR24_COMPRESSION: case B44_COMPRESSION: case B44A_COMPRESSION: + case DWAA_COMPRESSION: + case DWAB_COMPRESSION: - return true; + return true; default: - return false; + return false; } } +bool isValidDeepCompression(Compression c) +{ + switch(c) + { + case NO_COMPRESSION: + case RLE_COMPRESSION: + case ZIPS_COMPRESSION: + return true; + default : + return false; + } +} + Compressor * newCompressor (Compression c, size_t maxScanLineSize, const Header &hdr) @@ -116,77 +133,94 @@ newCompressor (Compression c, size_t maxScanLineSize, const Header &hdr) { case RLE_COMPRESSION: - return new RleCompressor (hdr, maxScanLineSize); + return new RleCompressor (hdr, maxScanLineSize); case ZIPS_COMPRESSION: - return new ZipCompressor (hdr, maxScanLineSize, 1); + return new ZipCompressor (hdr, maxScanLineSize, 1); case ZIP_COMPRESSION: - return new ZipCompressor (hdr, maxScanLineSize, 16); + return new ZipCompressor (hdr, maxScanLineSize, 16); case PIZ_COMPRESSION: - return new PizCompressor (hdr, maxScanLineSize, 32); + return new PizCompressor (hdr, maxScanLineSize, 32); case PXR24_COMPRESSION: - return new Pxr24Compressor (hdr, maxScanLineSize, 16); + return new Pxr24Compressor (hdr, maxScanLineSize, 16); case B44_COMPRESSION: - return new B44Compressor (hdr, maxScanLineSize, 32, false); + return new B44Compressor (hdr, maxScanLineSize, 32, false); case B44A_COMPRESSION: - return new B44Compressor (hdr, maxScanLineSize, 32, true); + return new B44Compressor (hdr, maxScanLineSize, 32, true); + + case DWAA_COMPRESSION: + + return new DwaCompressor (hdr, maxScanLineSize, 32, + DwaCompressor::STATIC_HUFFMAN); + + case DWAB_COMPRESSION: + + return new DwaCompressor (hdr, maxScanLineSize, 256, + DwaCompressor::STATIC_HUFFMAN); default: - return 0; + return 0; } } Compressor * newTileCompressor (Compression c, - size_t tileLineSize, - size_t numTileLines, - const Header &hdr) + size_t tileLineSize, + size_t numTileLines, + const Header &hdr) { switch (c) { case RLE_COMPRESSION: - return new RleCompressor (hdr, uiMult (tileLineSize, numTileLines)); + return new RleCompressor (hdr, uiMult (tileLineSize, numTileLines)); case ZIPS_COMPRESSION: case ZIP_COMPRESSION: - return new ZipCompressor (hdr, tileLineSize, numTileLines); + return new ZipCompressor (hdr, tileLineSize, numTileLines); case PIZ_COMPRESSION: - return new PizCompressor (hdr, tileLineSize, numTileLines); + return new PizCompressor (hdr, tileLineSize, numTileLines); case PXR24_COMPRESSION: - return new Pxr24Compressor (hdr, tileLineSize, numTileLines); + return new Pxr24Compressor (hdr, tileLineSize, numTileLines); case B44_COMPRESSION: - return new B44Compressor (hdr, tileLineSize, numTileLines, false); + return new B44Compressor (hdr, tileLineSize, numTileLines, false); case B44A_COMPRESSION: - return new B44Compressor (hdr, tileLineSize, numTileLines, true); + return new B44Compressor (hdr, tileLineSize, numTileLines, true); + + case DWAA_COMPRESSION: + case DWAB_COMPRESSION: + + return new DwaCompressor (hdr, tileLineSize, numTileLines, + DwaCompressor::DEFLATE); default: - return 0; + return 0; } } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT + diff --git a/3rdparty/openexr/IlmImf/ImfCompressor.h b/3rdparty/openexr/IlmImf/ImfCompressor.h index 9987820805..958677865a 100644 --- a/3rdparty/openexr/IlmImf/ImfCompressor.h +++ b/3rdparty/openexr/IlmImf/ImfCompressor.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,13 +43,16 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfCompression.h" #include "ImathBox.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" + #include -namespace Imf { -class Header; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class Compressor @@ -61,6 +64,7 @@ class Compressor // that will be compressed or uncompressed //--------------------------------------------- + IMF_EXPORT Compressor (const Header &hdr); @@ -68,6 +72,7 @@ class Compressor // Destructor //----------- + IMF_EXPORT virtual ~Compressor (); @@ -76,6 +81,7 @@ class Compressor // a single call to compress() and uncompress(). //---------------------------------------------- + IMF_EXPORT virtual int numScanLines () const = 0; @@ -88,10 +94,11 @@ class Compressor enum Format { - NATIVE, // the machine's native format - XDR // Xdr format + NATIVE, // the machine's native format + XDR // Xdr format }; + IMF_EXPORT virtual Format format () const; @@ -155,15 +162,17 @@ class Compressor // //------------------------------------------------------------------------- + IMF_EXPORT virtual int compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr) = 0; + int inSize, + int minY, + const char *&outPtr) = 0; + IMF_EXPORT virtual int compressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); //------------------------------------------------------------------------- // Uncompress an array of bytes that has been compressed by compress(): @@ -181,15 +190,17 @@ class Compressor // //------------------------------------------------------------------------- + IMF_EXPORT virtual int uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr) = 0; + int inSize, + int minY, + const char *&outPtr) = 0; + IMF_EXPORT virtual int uncompressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); private: @@ -201,7 +212,15 @@ class Compressor // Test if c is a valid compression type //-------------------------------------- -bool isValidCompression (Compression c); +IMF_EXPORT +bool isValidCompression (Compression c); + +//-------------------------------------- +// Test if c is valid for deep data +//-------------------------------------- + +IMF_EXPORT +bool isValidDeepCompression (Compression c); //----------------------------------------------------------------- @@ -212,16 +231,17 @@ bool isValidCompression (Compression c); // // header Header of the input or output file whose // pixels will be compressed or uncompressed. -// +// // return value A pointer to a new Compressor object (it // is the caller's responsibility to delete // the object), or 0 (if c is NO_COMPRESSION). // //----------------------------------------------------------------- +IMF_EXPORT Compressor * newCompressor (Compression c, - size_t maxScanLineSize, - const Header &hdr); + size_t maxScanLineSize, + const Header &hdr); //----------------------------------------------------------------- @@ -241,12 +261,13 @@ Compressor * newCompressor (Compression c, // //----------------------------------------------------------------- +IMF_EXPORT Compressor * newTileCompressor (Compression c, - size_t tileLineSize, - size_t numTileLines, - const Header &hdr); + size_t tileLineSize, + size_t numTileLines, + const Header &hdr); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfConvert.cpp b/3rdparty/openexr/IlmImf/ImfConvert.cpp index c94a5027c7..cce7163c19 100644 --- a/3rdparty/openexr/IlmImf/ImfConvert.cpp +++ b/3rdparty/openexr/IlmImf/ImfConvert.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -40,10 +40,14 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfConvert.h" +#include "ImfNamespace.h" + #include -namespace Imf { + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + namespace { inline bool @@ -88,10 +92,10 @@ unsigned int halfToUint (half h) { if (h.isNegative() || h.isNan()) - return 0; + return 0; if (h.isInfinity()) - return UINT_MAX; + return UINT_MAX; return (unsigned int) h; } @@ -101,39 +105,39 @@ unsigned int floatToUint (float f) { if (isNegative (f) || isNan (f)) - return 0; + return 0; if (isInfinity (f) || f > UINT_MAX) - return UINT_MAX; + return UINT_MAX; return (unsigned int) f; } -half +half uintToHalf (unsigned int ui) { if (ui > HALF_MAX) - return half::posInf(); + return half::posInf(); - return half (ui); + return half ((float) ui); } -half +half floatToHalf (float f) { if (isFinite (f)) { - if (f > HALF_MAX) - return half::posInf(); + if (f > HALF_MAX) + return half::posInf(); - if (f < -HALF_MAX) - return half::negInf(); + if (f < -HALF_MAX) + return half::negInf(); } return half (f); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfConvert.h b/3rdparty/openexr/IlmImf/ImfConvert.h index 00844dd2a0..b0a7f47d12 100644 --- a/3rdparty/openexr/IlmImf/ImfConvert.h +++ b/3rdparty/openexr/IlmImf/ImfConvert.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -47,9 +47,11 @@ //----------------------------------------------------------------------------- #include "half.h" +#include "ImfExport.h" +#include "ImfNamespace.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { //--------------------------------------------------------- // Conversion from half or float to unsigned int: @@ -70,8 +72,8 @@ namespace Imf { // //--------------------------------------------------------- -unsigned int halfToUint (half h); -unsigned int floatToUint (float f); +IMF_EXPORT unsigned int halfToUint (half h); +IMF_EXPORT unsigned int floatToUint (float f); //--------------------------------------------------------- @@ -95,10 +97,11 @@ unsigned int floatToUint (float f); // //--------------------------------------------------------- -half uintToHalf (unsigned int ui); -half floatToHalf (float f); +IMF_EXPORT half uintToHalf (unsigned int ui); +IMF_EXPORT half floatToHalf (float f); + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imf #endif diff --git a/3rdparty/openexr/IlmImf/ImfDeepCompositing.cpp b/3rdparty/openexr/IlmImf/ImfDeepCompositing.cpp new file mode 100644 index 0000000000..76702c1d4b --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepCompositing.cpp @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Weta Digital Ltd +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Weta Digital nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfDeepCompositing.h" + +#include "ImfNamespace.h" +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using std::sort; +using std::vector; +DeepCompositing::DeepCompositing() +{ +} + +DeepCompositing::~DeepCompositing() +{ +} + +void +DeepCompositing::composite_pixel (float outputs[], + const float* inputs[], + const char*channel_names[], + int num_channels, + int num_samples, + int sources) +{ + for(int i=0;i sort_order; + if(sources>1) + { + sort_order.resize(num_samples); + for(int i=0;i1) ? sort_order[i] : i; + float alpha=outputs[2]; + if(alpha>=1.0) return; + + for(int c=0;c inputs[0][b]) return false; + if(inputs[1][a] < inputs[1][b]) return true; + if(inputs[1][a] > inputs[1][b]) return false; + return asecond; +} + + +const DeepSlice & +DeepFrameBuffer::operator [] (const char name[]) const +{ + SliceMap::const_iterator i = _map.find (name); + + if (i == _map.end()) + { + THROW (IEX_NAMESPACE::ArgExc, + "Cannot find frame buffer slice \"" << name << "\"."); + } + + return i->second; +} + + +DeepSlice & +DeepFrameBuffer::operator [] (const string &name) +{ + return this->operator[] (name.c_str()); +} + + +const DeepSlice & +DeepFrameBuffer::operator [] (const string &name) const +{ + return this->operator[] (name.c_str()); +} + + +DeepSlice * +DeepFrameBuffer::findSlice (const char name[]) +{ + SliceMap::iterator i = _map.find (name); + return (i == _map.end())? 0: &i->second; +} + + +const DeepSlice * +DeepFrameBuffer::findSlice (const char name[]) const +{ + SliceMap::const_iterator i = _map.find (name); + return (i == _map.end())? 0: &i->second; +} + + +DeepSlice * +DeepFrameBuffer::findSlice (const string &name) +{ + return findSlice (name.c_str()); +} + + +const DeepSlice * +DeepFrameBuffer::findSlice (const string &name) const +{ + return findSlice (name.c_str()); +} + + +DeepFrameBuffer::Iterator +DeepFrameBuffer::begin () +{ + return _map.begin(); +} + + +DeepFrameBuffer::ConstIterator +DeepFrameBuffer::begin () const +{ + return _map.begin(); +} + + +DeepFrameBuffer::Iterator +DeepFrameBuffer::end () +{ + return _map.end(); +} + + +DeepFrameBuffer::ConstIterator +DeepFrameBuffer::end () const +{ + return _map.end(); +} + + +DeepFrameBuffer::Iterator +DeepFrameBuffer::find (const char name[]) +{ + return _map.find (name); +} + + +DeepFrameBuffer::ConstIterator +DeepFrameBuffer::find (const char name[]) const +{ + return _map.find (name); +} + + +DeepFrameBuffer::Iterator +DeepFrameBuffer::find (const string &name) +{ + return find (name.c_str()); +} + + +DeepFrameBuffer::ConstIterator +DeepFrameBuffer::find (const string &name) const +{ + return find (name.c_str()); +} + + +void +DeepFrameBuffer::insertSampleCountSlice(const Slice & slice) +{ + if (slice.type != UINT) + { + throw IEX_NAMESPACE::ArgExc("The type of sample count slice should be UINT."); + } + + _sampleCounts = slice; +} + + +const Slice & +DeepFrameBuffer::getSampleCountSlice() const +{ + return _sampleCounts; +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepFrameBuffer.h b/3rdparty/openexr/IlmImf/ImfDeepFrameBuffer.h new file mode 100644 index 0000000000..a3f062adcb --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepFrameBuffer.h @@ -0,0 +1,373 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFDEEPFRAMEBUFFER_H_ +#define IMFDEEPFRAMEBUFFER_H_ + +#include "ImfFrameBuffer.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//-------------------------------------------------------- +// Description of a single deep slice of the frame buffer: +//-------------------------------------------------------- + +struct DeepSlice : public Slice +{ + //--------------------------------------------------------------------- + // The stride for each sample in this slice. + // + // Memory layout: The address of sample i in pixel (x, y) is + // + // base + (xp / xSampling) * xStride + (yp / ySampling) * yStride + // + i * sampleStride + // + // where xp and yp are computed as follows: + // + // * If we are reading or writing a scanline-based file: + // + // xp = x + // yp = y + // + // * If we are reading a tile whose upper left coorner is at (xt, yt): + // + // if xTileCoords is true then xp = x - xt, else xp = x + // if yTileCoords is true then yp = y - yt, else yp = y + // + //--------------------------------------------------------------------- + + int sampleStride; + + //------------ + // Constructor + //------------ + IMF_EXPORT + DeepSlice (PixelType type = HALF, + char * base = 0, + size_t xStride = 0, + size_t yStride = 0, + size_t sampleStride = 0, + int xSampling = 1, + int ySampling = 1, + double fillValue = 0.0, + bool xTileCoords = false, + bool yTileCoords = false); +}; + +//----------------- +// DeepFrameBuffer. +//----------------- + +class DeepFrameBuffer +{ + public: + + + //------------ + // Add a slice + //------------ + + IMF_EXPORT + void insert (const char name[], + const DeepSlice &slice); + + IMF_EXPORT + void insert (const std::string &name, + const DeepSlice &slice); + + //---------------------------------------------------------------- + // Access to existing slices: + // + // [n] Returns a reference to the slice with name n. + // If no slice with name n exists, an IEX_NAMESPACE::ArgExc + // is thrown. + // + // findSlice(n) Returns a pointer to the slice with name n, + // or 0 if no slice with name n exists. + // + //---------------------------------------------------------------- + + IMF_EXPORT + DeepSlice & operator [] (const char name[]); + IMF_EXPORT + const DeepSlice & operator [] (const char name[]) const; + + IMF_EXPORT + DeepSlice & operator [] (const std::string &name); + IMF_EXPORT + const DeepSlice & operator [] (const std::string &name) const; + + IMF_EXPORT + DeepSlice * findSlice (const char name[]); + IMF_EXPORT + const DeepSlice * findSlice (const char name[]) const; + + IMF_EXPORT + DeepSlice * findSlice (const std::string &name); + IMF_EXPORT + const DeepSlice * findSlice (const std::string &name) const; + + + //----------------------------------------- + // Iterator-style access to existing slices + //----------------------------------------- + + typedef std::map SliceMap; + + class Iterator; + class ConstIterator; + + IMF_EXPORT + Iterator begin (); + IMF_EXPORT + ConstIterator begin () const; + + IMF_EXPORT + Iterator end (); + IMF_EXPORT + ConstIterator end () const; + + IMF_EXPORT + Iterator find (const char name[]); + IMF_EXPORT + ConstIterator find (const char name[]) const; + + IMF_EXPORT + Iterator find (const std::string &name); + IMF_EXPORT + ConstIterator find (const std::string &name) const; + + //---------------------------------------------------- + // Public function for accessing a sample count slice. + //---------------------------------------------------- + + IMF_EXPORT + void insertSampleCountSlice(const Slice & slice); + IMF_EXPORT + const Slice & getSampleCountSlice() const; + + private: + + SliceMap _map; + Slice _sampleCounts; +}; + +//---------- +// Iterators +//---------- + +class DeepFrameBuffer::Iterator +{ + public: + + IMF_EXPORT + Iterator (); + IMF_EXPORT + Iterator (const DeepFrameBuffer::SliceMap::iterator &i); + + IMF_EXPORT + Iterator & operator ++ (); + IMF_EXPORT + Iterator operator ++ (int); + + IMF_EXPORT + const char * name () const; + IMF_EXPORT + DeepSlice & slice () const; + + private: + + friend class DeepFrameBuffer::ConstIterator; + + DeepFrameBuffer::SliceMap::iterator _i; +}; + + +class DeepFrameBuffer::ConstIterator +{ + public: + + IMF_EXPORT + ConstIterator (); + IMF_EXPORT + ConstIterator (const DeepFrameBuffer::SliceMap::const_iterator &i); + IMF_EXPORT + ConstIterator (const DeepFrameBuffer::Iterator &other); + + IMF_EXPORT + ConstIterator & operator ++ (); + IMF_EXPORT + ConstIterator operator ++ (int); + + IMF_EXPORT + const char * name () const; + IMF_EXPORT + const DeepSlice & slice () const; + + private: + + friend bool operator == (const ConstIterator &, const ConstIterator &); + friend bool operator != (const ConstIterator &, const ConstIterator &); + + DeepFrameBuffer::SliceMap::const_iterator _i; +}; + + +//----------------- +// Inline Functions +//----------------- + +inline +DeepFrameBuffer::Iterator::Iterator (): _i() +{ + // empty +} + + +inline +DeepFrameBuffer::Iterator::Iterator (const DeepFrameBuffer::SliceMap::iterator &i): + _i (i) +{ + // empty +} + + +inline DeepFrameBuffer::Iterator & +DeepFrameBuffer::Iterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline DeepFrameBuffer::Iterator +DeepFrameBuffer::Iterator::operator ++ (int) +{ + Iterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +DeepFrameBuffer::Iterator::name () const +{ + return *_i->first; +} + + +inline DeepSlice & +DeepFrameBuffer::Iterator::slice () const +{ + return _i->second; +} + + +inline +DeepFrameBuffer::ConstIterator::ConstIterator (): _i() +{ + // empty +} + +inline +DeepFrameBuffer::ConstIterator::ConstIterator + (const DeepFrameBuffer::SliceMap::const_iterator &i): _i (i) +{ + // empty +} + + +inline +DeepFrameBuffer::ConstIterator::ConstIterator (const DeepFrameBuffer::Iterator &other): + _i (other._i) +{ + // empty +} + +inline DeepFrameBuffer::ConstIterator & +DeepFrameBuffer::ConstIterator::operator ++ () +{ + ++_i; + return *this; +} + + +inline DeepFrameBuffer::ConstIterator +DeepFrameBuffer::ConstIterator::operator ++ (int) +{ + ConstIterator tmp = *this; + ++_i; + return tmp; +} + + +inline const char * +DeepFrameBuffer::ConstIterator::name () const +{ + return *_i->first; +} + +inline const DeepSlice & +DeepFrameBuffer::ConstIterator::slice () const +{ + return _i->second; +} + + +inline bool +operator == (const DeepFrameBuffer::ConstIterator &x, + const DeepFrameBuffer::ConstIterator &y) +{ + return x._i == y._i; +} + + +inline bool +operator != (const DeepFrameBuffer::ConstIterator &x, + const DeepFrameBuffer::ConstIterator &y) +{ + return !(x == y); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + + +#endif /* IMFDEEPFRAMEBUFFER_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfDeepImageState.h b/3rdparty/openexr/IlmImf/ImfDeepImageState.h new file mode 100644 index 0000000000..a3941c46ad --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepImageState.h @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2013, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#ifndef INCLUDED_IMF_DEEPIMAGESTATE_H +#define INCLUDED_IMF_DEEPIMAGESTATE_H + +//----------------------------------------------------------------------------- +// +// enum DeepImageState -- describes how orderly the pixel data +// in a deep image are +// +// The samples in a deep image pixel may be sorted according to +// depth, and the sample depths or depth ranges may or may not +// overlap each other. A pixel is +// +// - SORTED if for every i and j with i < j +// +// (Z[i] < Z[j]) || (Z[i] == Z[j] && ZBack[i] < ZBack[j]), +// +// - NON_OVERLAPPING if for every i and j with i != j +// +// (Z[i] < Z[j] && ZBack[i] <= Z[j]) || +// (Z[j] < Z[i] && ZBack[j] <= Z[i]) || +// (Z[i] == Z[j] && ZBack[i] <= Z[i] & ZBack[j] > Z[j]) || +// (Z[i] == Z[j] && ZBack[j] <= Z[j] & ZBack[i] > Z[i]), +// +// - TIDY if it is SORTED and NON_OVERLAPPING, +// +// - MESSY if it is neither SORTED nor NON_OVERLAPPING. +// +// A deep image is +// +// - MESSY if at least one of its pixels is MESSY, +// - SORTED if all of its pixels are SORTED, +// - NON_OVERLAPPING if all of its pixels are NON_OVERLAPPING, +// - TIDY if all of its pixels are TIDY. +// +// Note: the rather complicated definition of NON_OVERLAPPING prohibits +// overlapping volume samples, coincident point samples and point samples +// in the middle of a volume sample, but it does allow point samples at +// the front or back of a volume sample. +// +//----------------------------------------------------------------------------- + +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +enum DeepImageState +{ + DIS_MESSY = 0, + DIS_SORTED = 1, + DIS_NON_OVERLAPPING = 2, + DIS_TIDY = 3, + + DIS_NUMSTATES // Number of different image states +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfDeepImageStateAttribute.cpp b/3rdparty/openexr/IlmImf/ImfDeepImageStateAttribute.cpp new file mode 100644 index 0000000000..86a70a6408 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepImageStateAttribute.cpp @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2013, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +//----------------------------------------------------------------------------- +// +// class DeepImageStateAttribute +// +//----------------------------------------------------------------------------- + +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; + +template <> +const char * +DeepImageStateAttribute::staticTypeName () +{ + return "deepImageState"; +} + + +template <> +void +DeepImageStateAttribute::writeValueTo + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const +{ + unsigned char tmp = _value; + Xdr::write (os, tmp); +} + + +template <> +void +DeepImageStateAttribute::readValueFrom + (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) +{ + unsigned char tmp; + Xdr::read (is, tmp); + _value = DeepImageState (tmp); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepImageStateAttribute.h b/3rdparty/openexr/IlmImf/ImfDeepImageStateAttribute.h new file mode 100644 index 0000000000..6174e9481c --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepImageStateAttribute.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2013, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMF_DEEPIMAGESTATE_ATTRIBUTE_H +#define INCLUDED_IMF_DEEPIMAGESTATE_ATTRIBUTE_H + + +//----------------------------------------------------------------------------- +// +// class DeepImageStateAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfDeepImageState.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +typedef TypedAttribute + DeepImageStateAttribute; + +template <> IMF_EXPORT const char *DeepImageStateAttribute::staticTypeName (); + +template <> IMF_EXPORT +void DeepImageStateAttribute::writeValueTo + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; + +template <> IMF_EXPORT +void DeepImageStateAttribute::readValueFrom + (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfDeepScanLineInputFile.cpp b/3rdparty/openexr/IlmImf/ImfDeepScanLineInputFile.cpp new file mode 100644 index 0000000000..b4246762a0 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepScanLineInputFile.cpp @@ -0,0 +1,2025 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +//----------------------------------------------------------------------------- +// +// class DeepScanLineInputFile +// +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ImfMultiPartInputFile.h" +#include "ImfDeepFrameBuffer.h" +#include "ImfInputStreamMutex.h" +#include "ImfInputPartData.h" + + +#include "ImathBox.h" +#include "ImathFun.h" + + +#include "IlmThreadPool.h" +#include "IlmThreadSemaphore.h" +#include "IlmThreadMutex.h" + +#include "Iex.h" + +#include +#include +#include +#include +#include + + +#include "ImfNamespace.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::divp; +using IMATH_NAMESPACE::modp; +using std::string; +using std::vector; +using std::ifstream; +using std::min; +using std::max; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using ILMTHREAD_NAMESPACE::Semaphore; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; + +namespace { + +struct InSliceInfo +{ + PixelType typeInFrameBuffer; + PixelType typeInFile; + char * base; + char* pointerArrayBase; + size_t xPointerStride; + size_t yPointerStride; + size_t sampleStride; + int xSampling; + int ySampling; + bool fill; + bool skip; + double fillValue; + + InSliceInfo (PixelType typeInFrameBuffer = HALF, + char * base = NULL, + PixelType typeInFile = HALF, + size_t xPointerStride = 0, + size_t yPointerStride = 0, + size_t sampleStride = 0, + int xSampling = 1, + int ySampling = 1, + bool fill = false, + bool skip = false, + double fillValue = 0.0); +}; + + +InSliceInfo::InSliceInfo (PixelType tifb, + char * b, + PixelType tifl, + size_t xpst, + size_t ypst, + size_t spst, + int xsm, int ysm, + bool f, bool s, + double fv) +: + typeInFrameBuffer (tifb), + typeInFile (tifl), + base(b), + xPointerStride (xpst), + yPointerStride (ypst), + sampleStride (spst), + xSampling (xsm), + ySampling (ysm), + fill (f), + skip (s), + fillValue (fv) +{ + // empty +} + + +struct LineBuffer +{ + const char * uncompressedData; + char * buffer; + Int64 packedDataSize; + Int64 unpackedDataSize; + + int minY; + int maxY; + Compressor * compressor; + Compressor::Format format; + int number; + bool hasException; + string exception; + + LineBuffer (); + ~LineBuffer (); + + inline void wait () {_sem.wait();} + inline void post () {_sem.post();} + + private: + + Semaphore _sem; +}; + + +LineBuffer::LineBuffer (): + uncompressedData (0), + buffer (0), + packedDataSize (0), + compressor (0), + format (defaultFormat(compressor)), + number (-1), + hasException (false), + exception (), + _sem (1) +{ + // empty +} + + +LineBuffer::~LineBuffer () +{ + if (compressor != 0) + delete compressor; +} + +} // namespace + + +struct DeepScanLineInputFile::Data: public Mutex +{ + Header header; // the image header + int version; // file's version + DeepFrameBuffer frameBuffer; // framebuffer to write into + LineOrder lineOrder; // order of the scanlines in file + int minX; // data window's min x coord + int maxX; // data window's max x coord + int minY; // data window's min y coord + int maxY; // data window's max x coord + vector lineOffsets; // stores offsets in file for + // each line + bool fileIsComplete; // True if no scanlines are missing + // in the file + int nextLineBufferMinY; // minimum y of the next linebuffer + vector bytesPerLine; // combined size of a line over all + // channels + vector offsetInLineBuffer; // offset for each scanline in its + // linebuffer + vector slices; // info about channels in file + + vector lineBuffers; // each holds one line buffer + int linesInBuffer; // number of scanlines each buffer + // holds + int partNumber; // part number + int numThreads; // number of threads + + bool multiPartBackwardSupport; // if we are reading a multipart file using single file API + MultiPartInputFile* multiPartFile; // for multipart files opened as single part + bool memoryMapped; // if the stream is memory mapped + + Array2D sampleCount; // the number of samples + // in each pixel + + Array lineSampleCount; // the number of samples + // in each line + + Array gotSampleCount; // for each scanline, indicating if + // we have got its sample count table + + char* sampleCountSliceBase; // pointer to the start of + // the sample count array + int sampleCountXStride; // x stride of the sample count array + int sampleCountYStride; // y stride of the sample count array + bool frameBufferValid; // set by setFrameBuffer: excepts if readPixelSampleCounts if false + + Array sampleCountTableBuffer; + // the buffer for sample count table + + Compressor* sampleCountTableComp; + // the decompressor for sample count table + + int combinedSampleSize; // total size of all channels combined: used to sanity check sample table size + + int maxSampleCountTableSize; + // the max size in bytes for a pixel + // sample count table + InputStreamMutex* _streamData; + bool _deleteStream; + + + Data (int numThreads); + ~Data (); + + inline LineBuffer * getLineBuffer (int number); // hash function from line + // buffer indices into our + // vector of line buffers +}; + + +DeepScanLineInputFile::Data::Data (int numThreads): + partNumber(-1), + numThreads(numThreads), + multiPartBackwardSupport(false), + multiPartFile(NULL), + memoryMapped(false), + frameBufferValid(false), + _streamData(NULL), + _deleteStream(false) +{ + // + // We need at least one lineBuffer, but if threading is used, + // to keep n threads busy we need 2*n lineBuffers + // + + lineBuffers.resize (max (1, 2 * numThreads)); + + for (size_t i = 0; i < lineBuffers.size(); i++) + lineBuffers[i] = 0; + + sampleCountTableComp = 0; +} + + +DeepScanLineInputFile::Data::~Data () +{ + for (size_t i = 0; i < lineBuffers.size(); i++) + if (lineBuffers[i] != 0) + delete lineBuffers[i]; + + for (size_t i = 0; i < slices.size(); i++) + delete slices[i]; + + if (sampleCountTableComp != 0) + delete sampleCountTableComp; + + if (multiPartBackwardSupport) + delete multiPartFile; +} + + +inline LineBuffer * +DeepScanLineInputFile::Data::getLineBuffer (int lineBufferNumber) +{ + return lineBuffers[lineBufferNumber % lineBuffers.size()]; +} + + +namespace { + + +void +reconstructLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + LineOrder lineOrder, + vector &lineOffsets) +{ + Int64 position = is.tellg(); + + try + { + for (unsigned int i = 0; i < lineOffsets.size(); i++) + { + Int64 lineOffset = is.tellg(); + + int y; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, y); + + Int64 packed_offset; + Int64 packed_sample; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_offset); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_sample); + //next is unpacked sample table size - skip this too + Xdr::skip (is, packed_offset+packed_sample+8); + + if (lineOrder == INCREASING_Y) + lineOffsets[i] = lineOffset; + else + lineOffsets[lineOffsets.size() - i - 1] = lineOffset; + } + } + catch (...) + { + // + // Suppress all exceptions. This functions is + // called only to reconstruct the line offset + // table for incomplete files, and exceptions + // are likely. + // + } + + is.clear(); + is.seekg (position); +} + + +void +readLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + LineOrder lineOrder, + vector &lineOffsets, + bool &complete) +{ + for (unsigned int i = 0; i < lineOffsets.size(); i++) + { + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, lineOffsets[i]); + } + + complete = true; + + for (unsigned int i = 0; i < lineOffsets.size(); i++) + { + if (lineOffsets[i] <= 0) + { + // + // Invalid data in the line offset table mean that + // the file is probably incomplete (the table is + // the last thing written to the file). Either + // some process is still busy writing the file, + // or writing the file was aborted. + // + // We should still be able to read the existing + // parts of the file. In order to do this, we + // have to make a sequential scan over the scan + // line data to reconstruct the line offset table. + // + + complete = false; + reconstructLineOffsets (is, lineOrder, lineOffsets); + break; + } + } +} + + +void +readPixelData (InputStreamMutex *streamData, + DeepScanLineInputFile::Data *ifd, + int minY, + char *&buffer, + Int64 &packedDataSize, + Int64 &unpackedDataSize) +{ + // + // Read a single line buffer from the input file. + // + // If the input file is not memory-mapped, we copy the pixel data into + // into the array pointed to by buffer. If the file is memory-mapped, + // then we change where buffer points to instead of writing into the + // array (hence buffer needs to be a reference to a char *). + // + + int lineBufferNumber = (minY - ifd->minY) / ifd->linesInBuffer; + + Int64 lineOffset = ifd->lineOffsets[lineBufferNumber]; + + if (lineOffset == 0) + THROW (IEX_NAMESPACE::InputExc, "Scan line " << minY << " is missing."); + + // + // Seek to the start of the scan line in the file, + // if necessary. + // + + if (!isMultiPart(ifd->version)) + { + if (ifd->nextLineBufferMinY != minY) + streamData->is->seekg (lineOffset); + } + else + { + // + // In a multi-part file, the file pointer may have been moved by + // other parts, so we have to ask tellg() where we are. + // + if (streamData->is->tellg() != ifd->lineOffsets[lineBufferNumber]) + streamData->is->seekg (lineOffset); + } + + // + // Read the data block's header. + // + + int yInFile; + + // + // Read the part number when we are dealing with a multi-part file. + // + + if (isMultiPart(ifd->version)) + { + int partNumber; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, partNumber); + if (partNumber != ifd->partNumber) + { + THROW (IEX_NAMESPACE::ArgExc, "Unexpected part number " << partNumber + << ", should be " << ifd->partNumber << "."); + } + } + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, yInFile); + + if (yInFile != minY) + throw IEX_NAMESPACE::InputExc ("Unexpected data block y coordinate."); + + Int64 sampleCountTableSize; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, sampleCountTableSize); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, packedDataSize); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, unpackedDataSize); + + + // + // We make a check on the data size requirements here. + // Whilst we wish to store 64bit sizes on disk, not all the compressors + // have been made to work with such data sizes and are still limited to + // using signed 32 bit (int) for the data size. As such, this version + // insists that we validate that the data size does not exceed the data + // type max limit. + // @TODO refactor the compressor code to ensure full 64-bit support. + // + + int compressorMaxDataSize = std::numeric_limits::max(); + if (packedDataSize > Int64(compressorMaxDataSize) || + unpackedDataSize > Int64(compressorMaxDataSize)) + { + THROW (IEX_NAMESPACE::ArgExc, "This version of the library does not support " + << "the allocation of data with size > " << compressorMaxDataSize + << " file unpacked size :" << unpackedDataSize + << " file packed size :" << packedDataSize << ".\n"); + } + + // + // Skip the pixel sample count table because we have read this data. + // + + Xdr::skip (*streamData->is, sampleCountTableSize); + + // + // Read the pixel data. + // + + if (streamData->is->isMemoryMapped ()) + buffer = streamData->is->readMemoryMapped (packedDataSize); + else + { + // (TODO) check if the packed data size is too big? + // (TODO) better memory management. Don't delete buffer all the time. + if (buffer != 0) delete[] buffer; + buffer = new char[packedDataSize]; + streamData->is->read (buffer, packedDataSize); + } + + // + // Keep track of which scan line is the next one in + // the file, so that we can avoid redundant seekg() + // operations (seekg() can be fairly expensive). + // + + if (ifd->lineOrder == INCREASING_Y) + ifd->nextLineBufferMinY = minY + ifd->linesInBuffer; + else + ifd->nextLineBufferMinY = minY - ifd->linesInBuffer; +} + +// +// A LineBufferTask encapsulates the task uncompressing a set of +// scanlines (line buffer) and copying them into the frame buffer. +// + +class LineBufferTask : public Task +{ + public: + + LineBufferTask (TaskGroup *group, + DeepScanLineInputFile::Data *ifd, + LineBuffer *lineBuffer, + int scanLineMin, + int scanLineMax); + + virtual ~LineBufferTask (); + + virtual void execute (); + + private: + + DeepScanLineInputFile::Data * _ifd; + LineBuffer * _lineBuffer; + int _scanLineMin; + int _scanLineMax; +}; + + +LineBufferTask::LineBufferTask + (TaskGroup *group, + DeepScanLineInputFile::Data *ifd, + LineBuffer *lineBuffer, + int scanLineMin, + int scanLineMax) +: + Task (group), + _ifd (ifd), + _lineBuffer (lineBuffer), + _scanLineMin (scanLineMin), + _scanLineMax (scanLineMax) +{ + // empty +} + + +LineBufferTask::~LineBufferTask () +{ + // + // Signal that the line buffer is now free + // + + _lineBuffer->post (); +} + + +void +LineBufferTask::execute () +{ + try + { + // + // Uncompress the data, if necessary + // + + if (_lineBuffer->uncompressedData == 0) + { + Int64 uncompressedSize = 0; + int maxY = min (_lineBuffer->maxY, _ifd->maxY); + + for (int i = _lineBuffer->minY - _ifd->minY; + i <= maxY - _ifd->minY; + ++i) + { + uncompressedSize += (int) _ifd->bytesPerLine[i]; + } + + // + // Create the compressor everytime when we want to use it, + // because we don't know maxBytesPerLine beforehand. + // (TODO) optimize this. don't do this every time. + // + + if (_lineBuffer->compressor != 0) + delete _lineBuffer->compressor; + Int64 maxBytesPerLine = 0; + for (int i = _lineBuffer->minY - _ifd->minY; + i <= maxY - _ifd->minY; + ++i) + { + if (_ifd->bytesPerLine[i] > maxBytesPerLine) + maxBytesPerLine = _ifd->bytesPerLine[i]; + } + _lineBuffer->compressor = newCompressor(_ifd->header.compression(), + maxBytesPerLine, + _ifd->header); + + if (_lineBuffer->compressor && + _lineBuffer->packedDataSize < uncompressedSize) + { + _lineBuffer->format = _lineBuffer->compressor->format(); + + _lineBuffer->packedDataSize = _lineBuffer->compressor->uncompress + (_lineBuffer->buffer, _lineBuffer->packedDataSize, + _lineBuffer->minY, _lineBuffer->uncompressedData); + } + else + { + // + // If the line is uncompressed, it's in XDR format, + // regardless of the compressor's output format. + // + + _lineBuffer->format = Compressor::XDR; + _lineBuffer->uncompressedData = _lineBuffer->buffer; + } + } + + int yStart, yStop, dy; + + if (_ifd->lineOrder == INCREASING_Y) + { + yStart = _scanLineMin; + yStop = _scanLineMax + 1; + dy = 1; + } + else + { + yStart = _scanLineMax; + yStop = _scanLineMin - 1; + dy = -1; + } + + for (int y = yStart; y != yStop; y += dy) + { + // + // Convert one scan line's worth of pixel data back + // from the machine-independent representation, and + // store the result in the frame buffer. + // + + const char *readPtr = _lineBuffer->uncompressedData + + _ifd->offsetInLineBuffer[y - _ifd->minY]; + + // + // Iterate over all image channels. + // + + for (unsigned int i = 0; i < _ifd->slices.size(); ++i) + { + // + // Test if scan line y of this channel contains any data + // (the scan line contains data only if y % ySampling == 0). + // + + InSliceInfo &slice = *_ifd->slices[i]; + + if (modp (y, slice.ySampling) != 0) + continue; + + // + // Find the x coordinates of the leftmost and rightmost + // sampled pixels (i.e. pixels within the data window + // for which x % xSampling == 0). + // + + // + // Fill the frame buffer with pixel data. + // + + if (slice.skip) + { + // + // The file contains data for this channel, but + // the frame buffer contains no slice for this channel. + // + + skipChannel (readPtr, slice.typeInFile, + _ifd->lineSampleCount[y - _ifd->minY]); + } + else + { + // + // The frame buffer contains a slice for this channel. + // + + int width = (_ifd->maxX - _ifd->minX + 1); + + copyIntoDeepFrameBuffer (readPtr, slice.base, + (char*) (&_ifd->sampleCount[0][0] + - _ifd->minX + - _ifd->minY * width), + sizeof(unsigned int) * 1, + sizeof(unsigned int) * width, + y, _ifd->minX, _ifd->maxX, + 0, 0, + 0, 0, + slice.sampleStride, + slice.xPointerStride, + slice.yPointerStride, + slice.fill, + slice.fillValue, _lineBuffer->format, + slice.typeInFrameBuffer, + slice.typeInFile); + } + } + } + } + catch (std::exception &e) + { + if (!_lineBuffer->hasException) + { + _lineBuffer->exception = e.what(); + _lineBuffer->hasException = true; + } + } + catch (...) + { + if (!_lineBuffer->hasException) + { + _lineBuffer->exception = "unrecognized exception"; + _lineBuffer->hasException = true; + } + } +} + + +LineBufferTask * +newLineBufferTask + (TaskGroup *group, + DeepScanLineInputFile::Data *ifd, + int number, + int scanLineMin, + int scanLineMax) +{ + // + // Wait for a line buffer to become available, fill the line + // buffer with raw data from the file if necessary, and create + // a new LineBufferTask whose execute() method will uncompress + // the contents of the buffer and copy the pixels into the + // frame buffer. + // + + LineBuffer *lineBuffer = ifd->getLineBuffer (number); + + try + { + lineBuffer->wait (); + + if (lineBuffer->number != number) + { + lineBuffer->minY = ifd->minY + number * ifd->linesInBuffer; + lineBuffer->maxY = lineBuffer->minY + ifd->linesInBuffer - 1; + + lineBuffer->number = number; + lineBuffer->uncompressedData = 0; + + readPixelData (ifd->_streamData, ifd, lineBuffer->minY, + lineBuffer->buffer, + lineBuffer->packedDataSize, + lineBuffer->unpackedDataSize); + } + } + catch (std::exception &e) + { + if (!lineBuffer->hasException) + { + lineBuffer->exception = e.what(); + lineBuffer->hasException = true; + } + lineBuffer->number = -1; + lineBuffer->post(); + throw; + } + catch (...) + { + // + // Reading from the file caused an exception. + // Signal that the line buffer is free, and + // re-throw the exception. + // + + lineBuffer->exception = "unrecognized exception"; + lineBuffer->hasException = true; + lineBuffer->number = -1; + lineBuffer->post(); + throw; + } + + scanLineMin = max (lineBuffer->minY, scanLineMin); + scanLineMax = min (lineBuffer->maxY, scanLineMax); + + return new LineBufferTask (group, ifd, lineBuffer, + scanLineMin, scanLineMax); +} + +} // namespace + + +void DeepScanLineInputFile::initialize(const Header& header) +{ + try + { + if (header.type() != DEEPSCANLINE) + throw IEX_NAMESPACE::ArgExc("Can't build a DeepScanLineInputFile from " + "a type-mismatched part."); + + if(header.version()!=1) + { + THROW(IEX_NAMESPACE::ArgExc, "Version " << header.version() << " not supported for deepscanline images in this version of the library"); + } + + _data->header = header; + + _data->lineOrder = _data->header.lineOrder(); + + const Box2i &dataWindow = _data->header.dataWindow(); + + _data->minX = dataWindow.min.x; + _data->maxX = dataWindow.max.x; + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; + + _data->sampleCount.resizeErase(_data->maxY - _data->minY + 1, + _data->maxX - _data->minX + 1); + _data->lineSampleCount.resizeErase(_data->maxY - _data->minY + 1); + + Compressor* compressor = newCompressor(_data->header.compression(), + 0, + _data->header); + + _data->linesInBuffer = numLinesInBuffer (compressor); + + delete compressor; + + _data->nextLineBufferMinY = _data->minY - 1; + + int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y + + _data->linesInBuffer) / _data->linesInBuffer; + + _data->lineOffsets.resize (lineOffsetSize); + + for (size_t i = 0; i < _data->lineBuffers.size(); i++) + _data->lineBuffers[i] = new LineBuffer (); + + _data->gotSampleCount.resizeErase(_data->maxY - _data->minY + 1); + for (int i = 0; i < _data->maxY - _data->minY + 1; i++) + _data->gotSampleCount[i] = false; + + _data->maxSampleCountTableSize = min(_data->linesInBuffer, _data->maxY - _data->minY + 1) * + (_data->maxX - _data->minX + 1) * + sizeof(unsigned int); + + _data->sampleCountTableBuffer.resizeErase(_data->maxSampleCountTableSize); + + _data->sampleCountTableComp = newCompressor(_data->header.compression(), + _data->maxSampleCountTableSize, + _data->header); + + _data->bytesPerLine.resize (_data->maxY - _data->minY + 1); + + const ChannelList & c=header.channels(); + + _data->combinedSampleSize=0; + for(ChannelList::ConstIterator i=c.begin();i!=c.end();i++) + { + switch(i.channel().type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF : + _data->combinedSampleSize+=Xdr::size(); + break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT : + _data->combinedSampleSize+=Xdr::size(); + break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT : + _data->combinedSampleSize+=Xdr::size(); + break; + default : + THROW(IEX_NAMESPACE::ArgExc, "Bad type for channel " << i.name() << " initializing deepscanline reader"); + + } + } + + } + catch (...) + { + delete _data; + _data=NULL; + throw; + } +} + + +DeepScanLineInputFile::DeepScanLineInputFile(InputPartData* part) + +{ + + _data = new Data(part->numThreads); + _data->_deleteStream=false; + _data->_streamData = part->mutex; + _data->memoryMapped = _data->_streamData->is->isMemoryMapped(); + _data->version = part->version; + + initialize(part->header); + + _data->lineOffsets = part->chunkOffsets; + + _data->partNumber = part->partNumber; +} + + +DeepScanLineInputFile::DeepScanLineInputFile + (const char fileName[], int numThreads) +: + _data (new Data (numThreads)) +{ + _data->_streamData = new InputStreamMutex(); + _data->_deleteStream = true; + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream* is = 0; + + try + { + is = new StdIFStream (fileName); + readMagicNumberAndVersionField(*is, _data->version); + // + // Backward compatibility to read multpart file. + // + if (isMultiPart(_data->version)) + { + compatibilityInitialize(*is); + return; + } + _data->_streamData->is = is; + _data->memoryMapped = is->isMemoryMapped(); + _data->header.readFrom (*_data->_streamData->is, _data->version); + _data->header.sanityCheck (isTiled (_data->version)); + + initialize(_data->header); + + readLineOffsets (*_data->_streamData->is, + _data->lineOrder, + _data->lineOffsets, + _data->fileIsComplete); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + if (is) delete is; + if (_data && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + REPLACE_EXC (e, "Cannot read image file " + "\"" << fileName << "\". " << e.what()); + throw; + } + catch (...) + { + if (is) delete is; + if (_data && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + throw; + } +} + + +DeepScanLineInputFile::DeepScanLineInputFile + (const Header &header, + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, + int version, + int numThreads) +: + _data (new Data (numThreads)) +{ + _data->_streamData=new InputStreamMutex(); + _data->_deleteStream=false; + _data->_streamData->is = is; + + _data->memoryMapped = is->isMemoryMapped(); + + _data->version =version; + + initialize (header); + + readLineOffsets (*_data->_streamData->is, + _data->lineOrder, + _data->lineOffsets, + _data->fileIsComplete); +} + + +DeepScanLineInputFile::~DeepScanLineInputFile () +{ + if (_data->_deleteStream) + delete _data->_streamData->is; + + if (_data) + { + if (!_data->memoryMapped) + for (size_t i = 0; i < _data->lineBuffers.size(); i++) + delete [] _data->lineBuffers[i]->buffer; + + // + // Unless this file was opened via the multipart API, delete the streamdata + // object too. + // (TODO) it should be "isMultiPart(data->version)", but when there is only + // single part, + // (see the above constructor) the version field is not set. + // + // (TODO) we should have a way to tell if the stream data is owned by this + // file or by a parent multipart file. + // + + if (_data->partNumber == -1 && _data->_streamData) + delete _data->_streamData; + + delete _data; + } +} + +void +DeepScanLineInputFile::compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is) +{ + is.seekg(0); + // + // Construct a MultiPartInputFile, initialize TiledInputFile + // with the part 0 data. + // (TODO) maybe change the third parameter of the constructor of MultiPartInputFile later. + // + _data->multiPartBackwardSupport = true; + _data->multiPartFile = new MultiPartInputFile(is, _data->numThreads); + InputPartData* part = _data->multiPartFile->getPart(0); + + multiPartInitialize(part); +} + +void DeepScanLineInputFile::multiPartInitialize(InputPartData* part) +{ + + _data->_streamData = part->mutex; + _data->memoryMapped = _data->_streamData->is->isMemoryMapped(); + _data->version = part->version; + + initialize(part->header); + + _data->lineOffsets = part->chunkOffsets; + + _data->partNumber = part->partNumber; + +} + + +const char * +DeepScanLineInputFile::fileName () const +{ + return _data->_streamData->is->fileName(); +} + + +const Header & +DeepScanLineInputFile::header () const +{ + return _data->header; +} + + +int +DeepScanLineInputFile::version () const +{ + return _data->version; +} + + +void +DeepScanLineInputFile::setFrameBuffer (const DeepFrameBuffer &frameBuffer) +{ + Lock lock (*_data->_streamData); + + + // + // Check if the new frame buffer descriptor is + // compatible with the image file header. + // + + const ChannelList &channels = _data->header.channels(); + + for (DeepFrameBuffer::ConstIterator j = frameBuffer.begin(); + j != frameBuffer.end(); + ++j) + { + ChannelList::ConstIterator i = channels.find (j.name()); + + if (i == channels.end()) + continue; + + if (i.channel().xSampling != j.slice().xSampling || + i.channel().ySampling != j.slice().ySampling) + THROW (IEX_NAMESPACE::ArgExc, "X and/or y subsampling factors " + "of \"" << i.name() << "\" channel " + "of input file \"" << fileName() << "\" are " + "not compatible with the frame buffer's " + "subsampling factors."); + } + + // + // Store the pixel sample count table. + // (TODO) Support for different sampling rates? + // + + const Slice& sampleCountSlice = frameBuffer.getSampleCountSlice(); + if (sampleCountSlice.base == 0) + { + throw IEX_NAMESPACE::ArgExc ("Invalid base pointer, please set a proper sample count slice."); + } + else + { + _data->sampleCountSliceBase = sampleCountSlice.base; + _data->sampleCountXStride = sampleCountSlice.xStride; + _data->sampleCountYStride = sampleCountSlice.yStride; + } + + // + // Initialize the slice table for readPixels(). + // + + vector slices; + ChannelList::ConstIterator i = channels.begin(); + + for (DeepFrameBuffer::ConstIterator j = frameBuffer.begin(); + j != frameBuffer.end(); + ++j) + { + while (i != channels.end() && strcmp (i.name(), j.name()) < 0) + { + // + // Channel i is present in the file but not + // in the frame buffer; data for channel i + // will be skipped during readPixels(). + // + + slices.push_back (new InSliceInfo (i.channel().type, + NULL, + i.channel().type, + 0, + 0, + 0, // sampleStride + i.channel().xSampling, + i.channel().ySampling, + false, // fill + true, // skip + 0.0)); // fillValue + ++i; + } + + bool fill = false; + + if (i == channels.end() || strcmp (i.name(), j.name()) > 0) + { + // + // Channel i is present in the frame buffer, but not in the file. + // In the frame buffer, slice j will be filled with a default value. + // + + fill = true; + } + + slices.push_back (new InSliceInfo (j.slice().type, + j.slice().base, + fill? j.slice().type: + i.channel().type, + j.slice().xStride, + j.slice().yStride, + j.slice().sampleStride, + j.slice().xSampling, + j.slice().ySampling, + fill, + false, // skip + j.slice().fillValue)); + + + if (i != channels.end() && !fill) + ++i; + } + + // + // Client may want data to be filled in multiple arrays, + // so we reset gotSampleCount and bytesPerLine. + // + + for (long i = 0; i < _data->gotSampleCount.size(); i++) + _data->gotSampleCount[i] = false; + for (size_t i = 0; i < _data->bytesPerLine.size(); i++) + _data->bytesPerLine[i] = 0; + + // + // Store the new frame buffer. + // + + _data->frameBuffer = frameBuffer; + + for (size_t i = 0; i < _data->slices.size(); i++) + delete _data->slices[i]; + _data->slices = slices; + _data->frameBufferValid = true; +} + + +const DeepFrameBuffer & +DeepScanLineInputFile::frameBuffer () const +{ + Lock lock (*_data->_streamData); + return _data->frameBuffer; +} + + +bool +DeepScanLineInputFile::isComplete () const +{ + return _data->fileIsComplete; +} + + +void +DeepScanLineInputFile::readPixels (int scanLine1, int scanLine2) +{ + try + { + Lock lock (*_data->_streamData); + + if (_data->slices.size() == 0) + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data destination."); + + int scanLineMin = min (scanLine1, scanLine2); + int scanLineMax = max (scanLine1, scanLine2); + + if (scanLineMin < _data->minY || scanLineMax > _data->maxY) + throw IEX_NAMESPACE::ArgExc ("Tried to read scan line outside " + "the image file's data window."); + + for (int i = scanLineMin; i <= scanLineMax; i++) + { + if (_data->gotSampleCount[i - _data->minY] == false) + throw IEX_NAMESPACE::ArgExc ("Tried to read scan line without " + "knowing the sample counts, please" + "read the sample counts first."); + } + + + // + // We impose a numbering scheme on the lineBuffers where the first + // scanline is contained in lineBuffer 1. + // + // Determine the first and last lineBuffer numbers in this scanline + // range. We always attempt to read the scanlines in the order that + // they are stored in the file. + // + + int start, stop, dl; + + if (_data->lineOrder == INCREASING_Y) + { + start = (scanLineMin - _data->minY) / _data->linesInBuffer; + stop = (scanLineMax - _data->minY) / _data->linesInBuffer + 1; + dl = 1; + } + else + { + start = (scanLineMax - _data->minY) / _data->linesInBuffer; + stop = (scanLineMin - _data->minY) / _data->linesInBuffer - 1; + dl = -1; + } + + // + // Create a task group for all line buffer tasks. When the + // task group goes out of scope, the destructor waits until + // all tasks are complete. + // + + { + TaskGroup taskGroup; + + // + // Add the line buffer tasks. + // + // The tasks will execute in the order that they are created + // because we lock the line buffers during construction and the + // constructors are called by the main thread. Hence, in order + // for a successive task to execute the previous task which + // used that line buffer must have completed already. + // + + for (int l = start; l != stop; l += dl) + { + ThreadPool::addGlobalTask (newLineBufferTask (&taskGroup, + _data, l, + scanLineMin, + scanLineMax)); + } + + // + // finish all tasks + // + } + + // + // Exeption handling: + // + // LineBufferTask::execute() may have encountered exceptions, but + // those exceptions occurred in another thread, not in the thread + // that is executing this call to ScanLineInputFile::readPixels(). + // LineBufferTask::execute() has caught all exceptions and stored + // the exceptions' what() strings in the line buffers. + // Now we check if any line buffer contains a stored exception; if + // this is the case then we re-throw the exception in this thread. + // (It is possible that multiple line buffers contain stored + // exceptions. We re-throw the first exception we find and + // ignore all others.) + // + + const string *exception = 0; + + for (size_t i = 0; i < _data->lineBuffers.size(); ++i) + { + LineBuffer *lineBuffer = _data->lineBuffers[i]; + + if (lineBuffer->hasException && !exception) + exception = &lineBuffer->exception; + + lineBuffer->hasException = false; + } + + if (exception) + throw IEX_NAMESPACE::IoExc (*exception); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error reading pixel data from image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +void +DeepScanLineInputFile::readPixels (int scanLine) +{ + readPixels (scanLine, scanLine); +} + + +void +DeepScanLineInputFile::rawPixelData (int firstScanLine, + char *pixelData, + Int64 &pixelDataSize) +{ + + + int minY = lineBufferMinY + (firstScanLine, _data->minY, _data->linesInBuffer); + int lineBufferNumber = (minY - _data->minY) / _data->linesInBuffer; + + Int64 lineOffset = _data->lineOffsets[lineBufferNumber]; + + if (lineOffset == 0) + THROW (IEX_NAMESPACE::InputExc, "Scan line " << minY << " is missing."); + + + // enter the lock here - prevent another thread reseeking the file during read + Lock lock (*_data->_streamData); + + // + // Seek to the start of the scan line in the file, + // + + if (_data->_streamData->is->tellg() != _data->lineOffsets[lineBufferNumber]) + _data->_streamData->is->seekg (lineOffset); + + // + // Read the data block's header. + // + + int yInFile; + + // + // Read the part number when we are dealing with a multi-part file. + // + + if (isMultiPart(_data->version)) + { + int partNumber; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*_data->_streamData->is, partNumber); + if (partNumber != _data->partNumber) + { + THROW (IEX_NAMESPACE::ArgExc, "Unexpected part number " << partNumber + << ", should be " << _data->partNumber << "."); + } + } + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*_data->_streamData->is, yInFile); + + if (yInFile != minY) + throw IEX_NAMESPACE::InputExc ("Unexpected data block y coordinate."); + + Int64 sampleCountTableSize; + Int64 packedDataSize; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*_data->_streamData->is, sampleCountTableSize); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*_data->_streamData->is, packedDataSize); + + // total requirement for reading all the data + + Int64 totalSizeRequired=28+sampleCountTableSize+packedDataSize; + + bool big_enough = totalSizeRequired<=pixelDataSize; + + pixelDataSize = totalSizeRequired; + + // was the block we were given big enough? + if(!big_enough || pixelData==NULL) + { + // special case: seek stream back to start if we are at the beginning (regular reading pixels assumes it doesn't need to seek + // in single part files) + if(!isMultiPart(_data->version)) + { + if (_data->nextLineBufferMinY == minY) + _data->_streamData->is->seekg (lineOffset); + } + // leave lock here - bail before reading more data + return; + } + + // copy the values we have read into the output block + *(int *) pixelData = yInFile; + *(Int64 *) (pixelData+4) =sampleCountTableSize; + *(Int64 *) (pixelData+12) = packedDataSize; + + // didn't read the unpackedsize - do that now + Xdr::read (*_data->_streamData->is, *(Int64 *) (pixelData+20)); + + // read the actual data + _data->_streamData->is->read(pixelData+28, sampleCountTableSize+packedDataSize); + + // special case: seek stream back to start if we are at the beginning (regular reading pixels assumes it doesn't need to seek + // in single part files) + if(!isMultiPart(_data->version)) + { + if (_data->nextLineBufferMinY == minY) + _data->_streamData->is->seekg (lineOffset); + } + + // leave lock here + +} + +void DeepScanLineInputFile::readPixels (const char* rawPixelData, + const DeepFrameBuffer& frameBuffer, + int scanLine1, + int scanLine2) const +{ + // + // read header from block - already converted from Xdr to native format + // + int data_scanline = *(int *) rawPixelData; + Int64 sampleCountTableDataSize=*(Int64 *) (rawPixelData+4); + Int64 packedDataSize = *(Int64 *) (rawPixelData+12); + Int64 unpackedDataSize = *(Int64 *) (rawPixelData+20); + + + + // + // Uncompress the data, if necessary + // + + + Compressor * decomp = NULL; + const char * uncompressed_data; + Compressor::Format format = Compressor::XDR; + if(packedDataSize header.compression(), + unpackedDataSize, + _data->header); + + decomp->uncompress(rawPixelData+28+sampleCountTableDataSize, + packedDataSize, + data_scanline, uncompressed_data); + format = decomp->format(); + } + else + { + // + // If the line is uncompressed, it's in XDR format, + // regardless of the compressor's output format. + // + + format = Compressor::XDR; + uncompressed_data = rawPixelData+28+sampleCountTableDataSize; + } + + + int yStart, yStop, dy; + + if (_data->lineOrder == INCREASING_Y) + { + yStart = scanLine1; + yStop = scanLine2 + 1; + dy = 1; + } + else + { + yStart = scanLine2; + yStop = scanLine1 - 1; + dy = -1; + } + + + + const char* samplecount_base = frameBuffer.getSampleCountSlice().base; + int samplecount_xstride = frameBuffer.getSampleCountSlice().xStride; + int samplecount_ystride = frameBuffer.getSampleCountSlice().yStride; + + // + // For each line within the block, get the count of bytes. + // + + int minYInLineBuffer = data_scanline; + int maxYInLineBuffer = min(minYInLineBuffer + _data->linesInBuffer - 1, _data->maxY); + + vector bytesPerLine(1+_data->maxY-_data->minY); + + + bytesPerDeepLineTable (_data->header, + minYInLineBuffer, + maxYInLineBuffer, + samplecount_base, + samplecount_xstride, + samplecount_ystride, + bytesPerLine); + + // + // For each scanline within the block, get the offset. + // + + vector offsetInLineBuffer; + offsetInLineBufferTable (bytesPerLine, + minYInLineBuffer - _data->minY, + maxYInLineBuffer - _data->minY, + _data->linesInBuffer, + offsetInLineBuffer); + + + const ChannelList & channels=header().channels(); + + + for (int y = yStart; y != yStop; y += dy) + { + + const char *readPtr =uncompressed_data + + offsetInLineBuffer[y - _data->minY]; + + // + // need to know the total number of samples on a scanline to skip channels + // compute on demand: -1 means uncomputed + // + int lineSampleCount = -1; + + + // + // Iterate over all image channels in frame buffer + // + + + ChannelList::ConstIterator i = channels.begin(); + + for (DeepFrameBuffer::ConstIterator j = frameBuffer.begin(); + j != frameBuffer.end(); + ++j) + { + while (i != channels.end() && strcmp (i.name(), j.name()) < 0) + { + // + // Channel i is present in the file but not + // in the frame buffer; skip + + if(lineSampleCount==-1) + { + lineSampleCount=0; + const char * ptr = (samplecount_base+y*samplecount_ystride + samplecount_xstride*_data->minX); + for(int x=_data->minX;x<=_data->maxX;x++) + { + + lineSampleCount+=*(const unsigned int *) ptr; + ptr+=samplecount_xstride; + } + } + + skipChannel (readPtr, i.channel().type, lineSampleCount ); + + ++i; + } + + bool fill = false; + + if (i == channels.end() || strcmp (i.name(), j.name()) > 0) + { + // + // Channel i is present in the frame buffer, but not in the file. + // In the frame buffer, slice j will be filled with a default value. + // + + fill = true; + } + if (modp (y, i.channel().ySampling) == 0) + { + + copyIntoDeepFrameBuffer (readPtr, j.slice().base, + samplecount_base, + samplecount_xstride, + samplecount_ystride, + y, _data->minX, _data->maxX, + 0, 0, + 0, 0, + j.slice().sampleStride, + j.slice().xStride, + j.slice().yStride, + fill, + j.slice().fillValue, + format, + j.slice().type, + i.channel().type); + + ++i; + + } + }//next slice in framebuffer + }//next row in image + + // + // clean up + // + + delete decomp; +} + + + +void DeepScanLineInputFile::readPixelSampleCounts (const char* rawPixelData, + const DeepFrameBuffer& frameBuffer, + int scanLine1, + int scanLine2) const +{ + // + // read header from block - already converted from Xdr to native format + // + int data_scanline = *(int *) rawPixelData; + Int64 sampleCountTableDataSize=*(Int64 *) (rawPixelData+4); + + + int maxY; + maxY = min(data_scanline + _data->linesInBuffer - 1, _data->maxY); + + if(scanLine1 != data_scanline) + { + THROW(IEX_NAMESPACE::ArgExc,"readPixelSampleCounts(rawPixelData,frameBuffer,"<< scanLine1 << ',' << scanLine2 << ") called with incorrect start scanline - should be " << data_scanline ); + } + + if(scanLine2 != maxY) + { + THROW(IEX_NAMESPACE::ArgExc,"readPixelSampleCounts(rawPixelData,frameBuffer,"<< scanLine1 << ',' << scanLine2 << ") called with incorrect end scanline - should be " << maxY ); + } + + + // + // If the sample count table is compressed, we'll uncompress it. + // + + Int64 rawSampleCountTableSize = (maxY - data_scanline + 1) * (_data->maxX - _data->minX + 1) * + Xdr::size (); + + + Compressor * decomp=NULL; + const char* readPtr; + if (sampleCountTableDataSize < rawSampleCountTableSize) + { + decomp = newCompressor(_data->header.compression(), + rawSampleCountTableSize, + _data->header); + + decomp->uncompress(rawPixelData+28, + sampleCountTableDataSize, + data_scanline, + readPtr); + } + else readPtr = rawPixelData+28; + + char* base = frameBuffer.getSampleCountSlice().base; + int xStride = frameBuffer.getSampleCountSlice().xStride; + int yStride = frameBuffer.getSampleCountSlice().yStride; + + + + for (int y = scanLine1; y <= scanLine2; y++) + { + int lastAccumulatedCount = 0; + for (int x = _data->minX; x <= _data->maxX; x++) + { + int accumulatedCount, count; + + // + // Read the sample count for pixel (x, y). + // + + Xdr::read (readPtr, accumulatedCount); + if (x == _data->minX) + count = accumulatedCount; + else + count = accumulatedCount - lastAccumulatedCount; + lastAccumulatedCount = accumulatedCount; + + // + // Store the data in both internal and external data structure. + // + + sampleCount(base, xStride, yStride, x, y) = count; + } + } + + if(decomp) + { + delete decomp; + } +} + + + +namespace +{ + +void +readSampleCountForLineBlock(InputStreamMutex* streamData, + DeepScanLineInputFile::Data* data, + int lineBlockId) +{ + streamData->is->seekg(data->lineOffsets[lineBlockId]); + + if (isMultiPart(data->version)) + { + int partNumber; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, partNumber); + + if (partNumber != data->partNumber) + throw IEX_NAMESPACE::ArgExc("Unexpected part number."); + } + + int minY; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, minY); + + // + // Check the correctness of minY. + // + + if (minY != data->minY + lineBlockId * data->linesInBuffer) + throw IEX_NAMESPACE::ArgExc("Unexpected data block y coordinate."); + + int maxY; + maxY = min(minY + data->linesInBuffer - 1, data->maxY); + + Int64 sampleCountTableDataSize; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, sampleCountTableDataSize); + + + + if(sampleCountTableDataSize>data->maxSampleCountTableSize) + { + THROW (IEX_NAMESPACE::ArgExc, "Bad sampleCountTableDataSize read from chunk "<< lineBlockId << ": expected " << data->maxSampleCountTableSize << " or less, got "<< sampleCountTableDataSize); + } + + Int64 packedDataSize; + Int64 unpackedDataSize; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, packedDataSize); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, unpackedDataSize); + + + + // + // We make a check on the data size requirements here. + // Whilst we wish to store 64bit sizes on disk, not all the compressors + // have been made to work with such data sizes and are still limited to + // using signed 32 bit (int) for the data size. As such, this version + // insists that we validate that the data size does not exceed the data + // type max limit. + // @TODO refactor the compressor code to ensure full 64-bit support. + // + + int compressorMaxDataSize = std::numeric_limits::max(); + if (sampleCountTableDataSize > Int64(compressorMaxDataSize)) + { + THROW (IEX_NAMESPACE::ArgExc, "This version of the library does not " + << "support the allocation of data with size > " + << compressorMaxDataSize + << " file table size :" << sampleCountTableDataSize << ".\n"); + } + streamData->is->read(data->sampleCountTableBuffer, sampleCountTableDataSize); + + const char* readPtr; + + // + // If the sample count table is compressed, we'll uncompress it. + // + + + if (sampleCountTableDataSize < data->maxSampleCountTableSize) + { + if(!data->sampleCountTableComp) + { + THROW(IEX_NAMESPACE::ArgExc,"Deep scanline data corrupt at chunk " << lineBlockId << " (sampleCountTableDataSize error)"); + } + data->sampleCountTableComp->uncompress(data->sampleCountTableBuffer, + sampleCountTableDataSize, + minY, + readPtr); + } + else readPtr = data->sampleCountTableBuffer; + + char* base = data->sampleCountSliceBase; + int xStride = data->sampleCountXStride; + int yStride = data->sampleCountYStride; + + // total number of samples in block: used to check samplecount table doesn't + // reference more data than exists + + size_t cumulative_total_samples=0; + + for (int y = minY; y <= maxY; y++) + { + int yInDataWindow = y - data->minY; + data->lineSampleCount[yInDataWindow] = 0; + + int lastAccumulatedCount = 0; + for (int x = data->minX; x <= data->maxX; x++) + { + int accumulatedCount, count; + + // + // Read the sample count for pixel (x, y). + // + + Xdr::read (readPtr, accumulatedCount); + + // sample count table should always contain monotonically + // increasing values. + if (accumulatedCount < lastAccumulatedCount) + { + THROW(IEX_NAMESPACE::ArgExc,"Deep scanline sampleCount data corrupt at chunk " << lineBlockId << " (negative sample count detected)"); + } + + count = accumulatedCount - lastAccumulatedCount; + lastAccumulatedCount = accumulatedCount; + + // + // Store the data in both internal and external data structure. + // + + data->sampleCount[yInDataWindow][x - data->minX] = count; + data->lineSampleCount[yInDataWindow] += count; + sampleCount(base, xStride, yStride, x, y) = count; + } + cumulative_total_samples+=data->lineSampleCount[yInDataWindow]; + if(cumulative_total_samples*data->combinedSampleSize > unpackedDataSize) + { + THROW(IEX_NAMESPACE::ArgExc,"Deep scanline sampleCount data corrupt at chunk " << lineBlockId << ": pixel data only contains " << unpackedDataSize + << " bytes of data but table references at least " << cumulative_total_samples*data->combinedSampleSize << " bytes of sample data" ); + } + data->gotSampleCount[y - data->minY] = true; + } +} + + +void +fillSampleCountFromCache(int y, DeepScanLineInputFile::Data* data) +{ + int yInDataWindow = y - data->minY; + char* base = data->sampleCountSliceBase; + int xStride = data->sampleCountXStride; + int yStride = data->sampleCountYStride; + + for (int x = data->minX; x <= data->maxX; x++) + { + unsigned int count = data->sampleCount[yInDataWindow][x - data->minX]; + sampleCount(base, xStride, yStride, x, y) = count; + } +} + +} // namespace + +void +DeepScanLineInputFile::readPixelSampleCounts (int scanline1, int scanline2) +{ + Int64 savedFilePos = 0; + + if(!_data->frameBufferValid) + { + throw IEX_NAMESPACE::ArgExc("readPixelSampleCounts called with no valid frame buffer"); + } + + try + { + Lock lock (*_data->_streamData); + + savedFilePos = _data->_streamData->is->tellg(); + + int scanLineMin = min (scanline1, scanline2); + int scanLineMax = max (scanline1, scanline2); + + if (scanLineMin < _data->minY || scanLineMax > _data->maxY) + throw IEX_NAMESPACE::ArgExc ("Tried to read scan line sample counts outside " + "the image file's data window."); + + for (int i = scanLineMin; i <= scanLineMax; i++) + { + // + // if scanline is already read, it'll be in the cache + // otherwise, read from file, store in cache and in caller's framebuffer + // + if (_data->gotSampleCount[i - _data->minY]) + { + fillSampleCountFromCache(i,_data); + + }else{ + + int lineBlockId = ( i - _data->minY ) / _data->linesInBuffer; + + readSampleCountForLineBlock ( _data->_streamData, _data, lineBlockId ); + + int minYInLineBuffer = lineBlockId * _data->linesInBuffer + _data->minY; + int maxYInLineBuffer = min ( minYInLineBuffer + _data->linesInBuffer - 1, _data->maxY ); + + // + // For each line within the block, get the count of bytes. + // + + bytesPerDeepLineTable ( _data->header, + minYInLineBuffer, + maxYInLineBuffer, + _data->sampleCountSliceBase, + _data->sampleCountXStride, + _data->sampleCountYStride, + _data->bytesPerLine ); + + // + // For each scanline within the block, get the offset. + // + + offsetInLineBufferTable ( _data->bytesPerLine, + minYInLineBuffer - _data->minY, + maxYInLineBuffer - _data->minY, + _data->linesInBuffer, + _data->offsetInLineBuffer ); + } + } + + _data->_streamData->is->seekg(savedFilePos); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error reading sample count data from image " + "file \"" << fileName() << "\". " << e.what()); + + _data->_streamData->is->seekg(savedFilePos); + + throw; + } +} + +void +DeepScanLineInputFile::readPixelSampleCounts(int scanline) +{ + readPixelSampleCounts(scanline, scanline); +} + +int +DeepScanLineInputFile::firstScanLineInChunk(int y) const +{ + return int((y-_data->minY)/_data->linesInBuffer)*_data->linesInBuffer + _data->minY; +} + +int +DeepScanLineInputFile::lastScanLineInChunk(int y) const +{ + int minY = firstScanLineInChunk(y); + return min(minY+_data->linesInBuffer-1,_data->maxY); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepScanLineInputFile.h b/3rdparty/openexr/IlmImf/ImfDeepScanLineInputFile.h new file mode 100644 index 0000000000..7ef9cc241f --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepScanLineInputFile.h @@ -0,0 +1,294 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#ifndef INCLUDED_IMF_DEEP_SCAN_LINE_INPUT_FILE_H +#define INCLUDED_IMF_DEEP_SCAN_LINE_INPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class DeepScanLineInputFile +// +//----------------------------------------------------------------------------- + +#include "ImfThreading.h" +#include "ImfGenericInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfDeepScanLineOutputFile.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class DeepScanLineInputFile : public GenericInputFile +{ + public: + + //------------ + // Constructor + //------------ + + IMF_EXPORT + DeepScanLineInputFile (const char fileName[], + int numThreads = globalThreadCount()); + + IMF_EXPORT + DeepScanLineInputFile (const Header &header, OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, + int version, /*version field from file*/ + int numThreads = globalThreadCount()); + + + //----------------------------------------- + // Destructor -- deallocates internal data + // structures, but does not close the file. + //----------------------------------------- + + IMF_EXPORT + virtual ~DeepScanLineInputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + IMF_EXPORT + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + IMF_EXPORT + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + IMF_EXPORT + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the InputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readPixels() is called. + // The current frame buffer can be changed after each call + // to readPixels(). + //----------------------------------------------------------- + + IMF_EXPORT + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + IMF_EXPORT + const DeepFrameBuffer & frameBuffer () const; + + + //--------------------------------------------------------------- + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window are + // present in the input file, or false if any pixels are missing. + // (Another program may still be busy writing the file, or file + // writing may have been aborted prematurely.) + //--------------------------------------------------------------- + + IMF_EXPORT + bool isComplete () const; + + + //--------------------------------------------------------------- + // Read pixel data: + // + // readPixels(s1,s2) reads all scan lines with y coordinates + // in the interval [min (s1, s2), max (s1, s2)] from the file, + // and stores them in the current frame buffer. + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header.dataWindow().max.y] + // + // The scan lines can be read from the file in random order, and + // individual scan lines may be skipped or read multiple times. + // For maximum efficiency, the scan lines should be read in the + // order in which they were written to the file. + // + // readPixels(s) calls readPixels(s,s). + // + // If threading is enabled, readPixels (s1, s2) tries to perform + // decopmression of multiple scanlines in parallel. + // + //--------------------------------------------------------------- + + IMF_EXPORT + void readPixels (int scanLine1, int scanLine2); + IMF_EXPORT + void readPixels (int scanLine); + + + + //--------------------------------------------------------------- + // Extract pixel data from pre-read block + // + // readPixels(rawPixelData,frameBuffer,s1,s2) reads all scan lines with y coordinates + // in the interval [min (s1, s2), max (s1, s2)] from the data provided and + // stores them in the provided frameBuffer. + // the data can be obtained from a call to rawPixelData() + // + // + // Both s1 and s2 must be within the data specified + // + // you must provide a frameBuffer with a samplecountslice, which must have been read + // and the data valid - readPixels uses your sample count buffer to compute + // offsets to the data it needs + // + // This call does not block, and is thread safe for clients with an existing + // threading model. The InputFile's frameBuffer is not used in this call. + // + // This call is only provided for clients which have an existing threading model in place + // and unpredictable access patterns to the data. + // The fastest way to read an entire image is to enable threading,use setFrameBuffer then + // readPixels(header().dataWindow().min.y, header.dataWindow().max.y) + // + //--------------------------------------------------------------- + + IMF_EXPORT + void readPixels (const char * rawPixelData, + const DeepFrameBuffer & frameBuffer, + int scanLine1, + int scanLine2) const; + + //---------------------------------------------- + // Read a block of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement OutputFile::copyPixels()). + // note: returns the entire payload of the relevant chunk of data, not including part number + // including compressed and uncompressed sizes + // on entry, if pixelDataSize is insufficiently large, no bytes are read (pixelData can safely be NULL) + // on exit, pixelDataSize is the number of bytes required to read the chunk + // + //---------------------------------------------- + + IMF_EXPORT + void rawPixelData (int firstScanLine, + char * pixelData, + Int64 &pixelDataSize); + + + //------------------------------------------------- + // firstScanLineInChunk() returns the row number of the first row that's stored in the + // same chunk as scanline y. Depending on the compression mode, this may not be the same as y + // + // lastScanLineInChunk() returns the row number of the last row that's stored in the same + // chunk as scanline y. Depending on the compression mode, this may not be the same as y. + // The last chunk in the file may be smaller than all the others + // + //------------------------------------------------ + IMF_EXPORT + int firstScanLineInChunk(int y) const; + IMF_EXPORT + int lastScanLineInChunk (int y) const; + + //----------------------------------------------------------- + // Read pixel sample counts into a slice in the frame buffer. + // + // readPixelSampleCounts(s1, s2) reads all the counts of + // pixel samples with y coordinates in the interval + // [min (s1, s2), max (s1, s2)] from the file, and stores + // them in the slice naming "sample count". + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header.dataWindow().max.y] + // + // readPixelSampleCounts(s) calls readPixelSampleCounts(s,s). + // + //----------------------------------------------------------- + + IMF_EXPORT + void readPixelSampleCounts (int scanline1, + int scanline2); + IMF_EXPORT + void readPixelSampleCounts (int scanline); + + + //---------------------------------------------------------- + // Read pixel sample counts into the provided frameBuffer + // using a block read of data read by rawPixelData + // for multi-scanline compression schemes, you must decode the entire block + // so scanline1=firstScanLineInChunk(y) and scanline2=lastScanLineInChunk(y) + // + // This call does not block, and is thread safe for clients with an existing + // threading model. The InputFile's frameBuffer is not used in this call. + // + // The fastest way to read an entire image is to enable threading in OpenEXR, use setFrameBuffer then + // readPixelSampleCounts(header().dataWindow().min.y, header.dataWindow().max.y) + // + //---------------------------------------------------------- + IMF_EXPORT + void readPixelSampleCounts (const char * rawdata , + const DeepFrameBuffer & frameBuffer, + int scanLine1 , + int scanLine2) const; + + struct Data; + + private: + + Data * _data; + + DeepScanLineInputFile (InputPartData* part); + + void initialize(const Header& header); + void compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream & is); + void multiPartInitialize(InputPartData* part); + + friend class InputFile; + friend class MultiPartInputFile; + friend void DeepScanLineOutputFile::copyPixels(DeepScanLineInputFile &); +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfDeepScanLineInputPart.cpp b/3rdparty/openexr/IlmImf/ImfDeepScanLineInputPart.cpp new file mode 100644 index 0000000000..068e1d4af3 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepScanLineInputPart.cpp @@ -0,0 +1,149 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#include "ImfDeepScanLineInputPart.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +DeepScanLineInputPart::DeepScanLineInputPart(MultiPartInputFile& multiPartFile, int partNumber) +{ + file = multiPartFile.getInputPart(partNumber); +} + + +const char * +DeepScanLineInputPart::fileName () const +{ + return file->fileName(); +} + + +const Header & +DeepScanLineInputPart::header () const +{ + return file->header(); +} + + +int +DeepScanLineInputPart::version () const +{ + return file->version(); +} + + +void +DeepScanLineInputPart::setFrameBuffer (const DeepFrameBuffer &frameBuffer) +{ + file->setFrameBuffer(frameBuffer); +} + + +const DeepFrameBuffer & +DeepScanLineInputPart::frameBuffer () const +{ + return file->frameBuffer(); +} + + +bool +DeepScanLineInputPart::isComplete () const +{ + return file->isComplete(); +} + + +void +DeepScanLineInputPart::readPixels (int scanLine1, int scanLine2) +{ + file->readPixels(scanLine1, scanLine2); +} + + +void +DeepScanLineInputPart::readPixels (int scanLine) +{ + file->readPixels(scanLine); +} + + +void +DeepScanLineInputPart::rawPixelData (int firstScanLine, + char *pixelData, + Int64 &pixelDataSize) +{ + file->rawPixelData(firstScanLine, pixelData, pixelDataSize); +} + + +void +DeepScanLineInputPart::readPixelSampleCounts(int scanline1, + int scanline2) +{ + file->readPixelSampleCounts(scanline1, scanline2); +} + + +void +DeepScanLineInputPart::readPixelSampleCounts(int scanline) +{ + file->readPixelSampleCounts(scanline); +} + +int +DeepScanLineInputPart::firstScanLineInChunk(int y) const +{ + return file->firstScanLineInChunk(y); +} + +int +DeepScanLineInputPart::lastScanLineInChunk(int y) const +{ + return file->lastScanLineInChunk(y); +} + +void +DeepScanLineInputPart::readPixels(const char* rawPixelData, const DeepFrameBuffer& frameBuffer, int scanLine1, int scanLine2) const +{ + return file->readPixels(rawPixelData,frameBuffer,scanLine1,scanLine2); +} +void +DeepScanLineInputPart::readPixelSampleCounts(const char* rawdata, const DeepFrameBuffer& frameBuffer, int scanLine1, int scanLine2) const +{ + return file->readPixelSampleCounts(rawdata,frameBuffer,scanLine1,scanLine2); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepScanLineInputPart.h b/3rdparty/openexr/IlmImf/ImfDeepScanLineInputPart.h new file mode 100644 index 0000000000..89245c8656 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepScanLineInputPart.h @@ -0,0 +1,197 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#ifndef IMFDEEPSCANLINEINPUTPART_H_ +#define IMFDEEPSCANLINEINPUTPART_H_ + +#include "ImfMultiPartInputFile.h" +#include "ImfDeepScanLineInputFile.h" +#include "ImfDeepScanLineOutputFile.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class DeepScanLineInputPart +{ + public: + + IMF_EXPORT + DeepScanLineInputPart(MultiPartInputFile& file, int partNumber); + + //------------------------ + // Access to the file name + //------------------------ + + IMF_EXPORT + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + IMF_EXPORT + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + IMF_EXPORT + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the InputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readPixels() is called. + // The current frame buffer can be changed after each call + // to readPixels(). + //----------------------------------------------------------- + + IMF_EXPORT + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + IMF_EXPORT + const DeepFrameBuffer & frameBuffer () const; + + + //--------------------------------------------------------------- + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window are + // present in the input file, or false if any pixels are missing. + // (Another program may still be busy writing the file, or file + // writing may have been aborted prematurely.) + //--------------------------------------------------------------- + + IMF_EXPORT + bool isComplete () const; + + + //--------------------------------------------------------------- + // Read pixel data: + // + // readPixels(s1,s2) reads all scan lines with y coordinates + // in the interval [min (s1, s2), max (s1, s2)] from the file, + // and stores them in the current frame buffer. + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header.dataWindow().max.y] + // + // The scan lines can be read from the file in random order, and + // individual scan lines may be skipped or read multiple times. + // For maximum efficiency, the scan lines should be read in the + // order in which they were written to the file. + // + // readPixels(s) calls readPixels(s,s). + // + // If threading is enabled, readPixels (s1, s2) tries to perform + // decopmression of multiple scanlines in parallel. + // + //--------------------------------------------------------------- + + IMF_EXPORT + void readPixels (int scanLine1, int scanLine2); + IMF_EXPORT + void readPixels (int scanLine); + IMF_EXPORT + void readPixels (const char * rawPixelData,const DeepFrameBuffer & frameBuffer, + int scanLine1,int scanLine2) const; + + //---------------------------------------------- + // Read a block of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement OutputFile::copyPixels()). + //---------------------------------------------- + + IMF_EXPORT + void rawPixelData (int firstScanLine, + char * pixelData, + Int64 &pixelDataSize); + + + //----------------------------------------------------------- + // Read pixel sample counts into a slice in the frame buffer. + // + // readPixelSampleCounts(s1, s2) reads all the counts of + // pixel samples with y coordinates in the interval + // [min (s1, s2), max (s1, s2)] from the file, and stores + // them in the slice naming "sample count". + // + // Both s1 and s2 must be within the interval + // [header().dataWindow().min.y, header.dataWindow().max.y] + // + // readPixelSampleCounts(s) calls readPixelSampleCounts(s,s). + //----------------------------------------------------------- + + IMF_EXPORT + void readPixelSampleCounts(int scanline1, + int scanline2); + IMF_EXPORT + void readPixelSampleCounts(int scanline); + + IMF_EXPORT + void readPixelSampleCounts( const char * rawdata , const DeepFrameBuffer & frameBuffer, + int scanLine1 , int scanLine2) const; + + IMF_EXPORT + int firstScanLineInChunk(int y) const; + IMF_EXPORT + int lastScanLineInChunk (int y) const; + private: + DeepScanLineInputFile *file; + + // needed for copyPixels + friend void DeepScanLineOutputFile::copyPixels(DeepScanLineInputPart &); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif /* IMFDEEPSCANLINEINPUTPART_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputFile.cpp new file mode 100644 index 0000000000..5fe0be3fda --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputFile.cpp @@ -0,0 +1,1554 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +//----------------------------------------------------------------------------- +// +// class DeepScanLineOutputFile +// +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include "ImathBox.h" +#include "ImathFun.h" +#include +#include +#include +#include +#include "ImfDeepFrameBuffer.h" +#include "ImfOutputStreamMutex.h" +#include "ImfOutputPartData.h" + +#include "IlmThreadPool.h" +#include "IlmThreadSemaphore.h" +#include "IlmThreadMutex.h" +#include "Iex.h" +#include +#include +#include +#include +#include + +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::divp; +using IMATH_NAMESPACE::modp; +using std::string; +using std::vector; +using std::ofstream; +using std::min; +using std::max; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using ILMTHREAD_NAMESPACE::Semaphore; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; + +namespace { + + +struct OutSliceInfo +{ + PixelType type; + const char * base; + ptrdiff_t sampleStride; + ptrdiff_t xStride; + ptrdiff_t yStride; + int xSampling; + int ySampling; + bool zero; + + OutSliceInfo (PixelType type = HALF, + const char * base =NULL, + ptrdiff_t sampleStride = 0, + ptrdiff_t xStride = 0, + ptrdiff_t yStride =0, + int xSampling = 1, + int ySampling = 1, + bool zero = false); +}; + + +OutSliceInfo::OutSliceInfo (PixelType t, + const char * base, + ptrdiff_t spstride, + ptrdiff_t xst, + ptrdiff_t yst, + int xsm, int ysm, + bool z) +: + type (t), + base (base), + sampleStride (spstride), + xStride(xst), + yStride(yst), + xSampling (xsm), + ySampling (ysm), + zero (z) +{ + // empty +} + + +struct LineBuffer +{ + Array< Array > buffer; + Array consecutiveBuffer; + const char * dataPtr; + Int64 uncompressedDataSize; + Int64 dataSize; + Array sampleCountTableBuffer; + const char * sampleCountTablePtr; + Int64 sampleCountTableSize; + Compressor* sampleCountTableCompressor; + int minY; // the min y scanline stored + int maxY; // the max y scanline stored + int scanLineMin; // the min y scanline writing out + int scanLineMax; // the max y scanline writing out + Compressor * compressor; + bool partiallyFull; // has incomplete data + bool hasException; + string exception; + + LineBuffer (int linesInBuffer); + ~LineBuffer (); + + void wait () {_sem.wait();} + void post () {_sem.post();} + + private: + + Semaphore _sem; +}; + + +LineBuffer::LineBuffer (int linesInBuffer) : + dataPtr (0), + dataSize (0), + sampleCountTablePtr (0), + sampleCountTableCompressor (0), + compressor (0), + partiallyFull (false), + hasException (false), + exception (), + _sem (1) +{ + buffer.resizeErase(linesInBuffer); +} + + +LineBuffer::~LineBuffer () +{ + if (compressor != 0) + delete compressor; + + if (sampleCountTableCompressor != 0) + delete sampleCountTableCompressor; +} + +} // namespace + + +struct DeepScanLineOutputFile::Data +{ + Header header; // the image header + int version; // file format version + bool multipart; // from a multipart file + Int64 previewPosition; // file position for preview + DeepFrameBuffer frameBuffer; // framebuffer to write into + int currentScanLine; // next scanline to be written + int missingScanLines; // number of lines to write + LineOrder lineOrder; // the file's lineorder + int minX; // data window's min x coord + int maxX; // data window's max x coord + int minY; // data window's min y coord + int maxY; // data window's max x coord + vector lineOffsets; // stores offsets in file for + // each scanline + vector bytesPerLine; // combined size of a line over + // all channels + Compressor::Format format; // compressor's data format + vector slices; // info about channels in file + Int64 lineOffsetsPosition; // file position for line + // offset table + + vector lineBuffers; // each holds one line buffer + int linesInBuffer; // number of scanlines each + // buffer holds + int partNumber; // the output part number + + char* sampleCountSliceBase; // the pointer to the number + // of samples in each pixel + int sampleCountXStride; // the x stride for sampleCountSliceBase + int sampleCountYStride; // the y stride for sampleCountSliceBase + + Array lineSampleCount; // the number of samples + // in each line + + Int64 maxSampleCountTableSize; + // the max size in bytes for a pixel + // sample count table + OutputStreamMutex* _streamData; + bool _deleteStream; + + Data (int numThreads); + ~Data (); + + + inline LineBuffer * getLineBuffer (int number);// hash function from line + // buffer indices into our + // vector of line buffers + + inline int& getSampleCount(int x, int y); // get the number of samples + // in each pixel +}; + + +DeepScanLineOutputFile::Data::Data (int numThreads): + lineOffsetsPosition (0), + partNumber (-1) , + _streamData(NULL), + _deleteStream(false) +{ + // + // We need at least one lineBuffer, but if threading is used, + // to keep n threads busy we need 2*n lineBuffers. + // + + lineBuffers.resize (max (1, 2 * numThreads)); + for (size_t i = 0; i < lineBuffers.size(); i++) + lineBuffers[i] = 0; +} + + +DeepScanLineOutputFile::Data::~Data () +{ + for (size_t i = 0; i < lineBuffers.size(); i++) + if (lineBuffers[i] != 0) + delete lineBuffers[i]; + + for (size_t i = 0; i < slices.size(); i++) + delete slices[i]; +} + + +int& +DeepScanLineOutputFile::Data::getSampleCount(int x, int y) +{ + return sampleCount(sampleCountSliceBase, + sampleCountXStride, + sampleCountYStride, + x, y); +} + + +LineBuffer* +DeepScanLineOutputFile::Data::getLineBuffer (int number) +{ + return lineBuffers[number % lineBuffers.size()]; +} + + +namespace { + +Int64 +writeLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const vector &lineOffsets) +{ + Int64 pos = os.tellp(); + + if (pos == -1) + IEX_NAMESPACE::throwErrnoExc ("Cannot determine current file position (%T)."); + + for (unsigned int i = 0; i < lineOffsets.size(); i++) + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, lineOffsets[i]); + + return pos; +} + + +void +writePixelData (OutputStreamMutex *filedata, + DeepScanLineOutputFile::Data *partdata, + int lineBufferMinY, + const char pixelData[], + Int64 packedDataSize, + Int64 unpackedDataSize, + const char sampleCountTableData[], + Int64 sampleCountTableSize) +{ + // + // Store a block of pixel data in the output file, and try + // to keep track of the current writing position the file + // without calling tellp() (tellp() can be fairly expensive). + // + + Int64 currentPosition = filedata->currentPosition; + filedata->currentPosition = 0; + + if (currentPosition == 0) + currentPosition = filedata->os->tellp(); + + partdata->lineOffsets[(partdata->currentScanLine - partdata->minY) / partdata->linesInBuffer] = + currentPosition; + + #ifdef DEBUG + + assert (filedata->os->tellp() == currentPosition); + + #endif + + // + // Write the optional part number. + // + + if (partdata->multipart) + { + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*filedata->os, partdata->partNumber); + } + + // + // Write the y coordinate of the first scanline in the chunk. + // + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*filedata->os, lineBufferMinY); + + // + // Write the packed size of the pixel sample count table. + // + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*filedata->os, sampleCountTableSize); + + // + // Write the packed pixel data size. + // + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*filedata->os, packedDataSize); + + // + // Write the unpacked pixel data size. + // + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*filedata->os, unpackedDataSize); + + // + // Write the packed pixel sample count table. + // + + filedata->os->write (sampleCountTableData, sampleCountTableSize); + + // + // Write the compressed data. + // + + filedata->os->write (pixelData, packedDataSize); + + // + // Update stream position. + // + + filedata->currentPosition = currentPosition + + Xdr::size() + // y coordinate + Xdr::size() + // packed sample count table size + Xdr::size() + // packed data size + Xdr::size() + // unpacked data size + sampleCountTableSize + // pixel sample count table + packedDataSize; // pixel data + + if (partdata->multipart) + { + filedata->currentPosition += Xdr::size(); // optional part number + } +} + + +inline void +writePixelData (OutputStreamMutex* filedata, + DeepScanLineOutputFile::Data *partdata, + const LineBuffer *lineBuffer) +{ + writePixelData (filedata, partdata, + lineBuffer->minY, + lineBuffer->dataPtr, + lineBuffer->dataSize, + lineBuffer->uncompressedDataSize, + lineBuffer->sampleCountTablePtr, + lineBuffer->sampleCountTableSize); +} + + +void +convertToXdr (DeepScanLineOutputFile::Data *ofd, + Array &lineBuffer, + int lineBufferMinY, + int lineBufferMaxY, + int inSize) +{ + // + // Convert the contents of a lineBuffer from the machine's native + // representation to Xdr format. This function is called by + // CompressLineBuffer::execute(), below, if the compressor wanted + // its input pixel data in the machine's native format, but then + // failed to compress the data (most compressors will expand rather + // than compress random input data). + // + // Note that this routine assumes that the machine's native + // representation of the pixel data has the same size as the + // Xdr representation. This makes it possible to convert the + // pixel data in place, without an intermediate temporary buffer. + // + + // + // Iterate over all scanlines in the lineBuffer to convert. + // + + char* writePtr = &lineBuffer[0]; + for (int y = lineBufferMinY; y <= lineBufferMaxY; y++) + { + // + // Set these to point to the start of line y. + // We will write to writePtr from readPtr. + // + + const char *readPtr = writePtr; + + // + // Iterate over all slices in the file. + // + + for (unsigned int i = 0; i < ofd->slices.size(); ++i) + { + // + // Test if scan line y of this channel is + // contains any data (the scan line contains + // data only if y % ySampling == 0). + // + + const OutSliceInfo &slice = *ofd->slices[i]; + + if (modp (y, slice.ySampling) != 0) + continue; + + // + // Find the number of sampled pixels, dMaxX-dMinX+1, for + // slice i in scan line y (i.e. pixels within the data window + // for which x % xSampling == 0). + // + + int xSampleCount = ofd->lineSampleCount[y - ofd->minY]; + + // + // Convert the samples in place. + // + + convertInPlace (writePtr, readPtr, slice.type, xSampleCount); + } + } +} + + +// +// A LineBufferTask encapsulates the task of copying a set of scanlines +// from the user's frame buffer into a LineBuffer object, compressing +// the data if necessary. +// + +class LineBufferTask: public Task +{ + public: + + LineBufferTask (TaskGroup *group, + DeepScanLineOutputFile::Data *ofd, + int number, + int scanLineMin, + int scanLineMax); + + virtual ~LineBufferTask (); + + virtual void execute (); + + private: + + DeepScanLineOutputFile::Data * _ofd; + LineBuffer * _lineBuffer; +}; + + +LineBufferTask::LineBufferTask + (TaskGroup *group, + DeepScanLineOutputFile::Data *ofd, + int number, + int scanLineMin, + int scanLineMax) +: + Task (group), + _ofd (ofd), + _lineBuffer (_ofd->getLineBuffer(number)) +{ + // + // Wait for the lineBuffer to become available + // + + _lineBuffer->wait (); + + // + // Initialize the lineBuffer data if necessary + // + + if (!_lineBuffer->partiallyFull) + { + + _lineBuffer->minY = _ofd->minY + number * _ofd->linesInBuffer; + + _lineBuffer->maxY = min (_lineBuffer->minY + _ofd->linesInBuffer - 1, + _ofd->maxY); + + _lineBuffer->partiallyFull = true; + } + + _lineBuffer->scanLineMin = max (_lineBuffer->minY, scanLineMin); + _lineBuffer->scanLineMax = min (_lineBuffer->maxY, scanLineMax); +} + + +LineBufferTask::~LineBufferTask () +{ + // + // Signal that the line buffer is now free + // + + _lineBuffer->post (); +} + + +void +LineBufferTask::execute () +{ + try + { + // + // First copy the pixel data from the + // frame buffer into the line buffer + // + + int yStart, yStop, dy; + + if (_ofd->lineOrder == INCREASING_Y) + { + yStart = _lineBuffer->scanLineMin; + yStop = _lineBuffer->scanLineMax + 1; + dy = 1; + } + else + { + yStart = _lineBuffer->scanLineMax; + yStop = _lineBuffer->scanLineMin - 1; + dy = -1; + } + + // + // Allocate buffers for scanlines. + // And calculate the sample counts for each line. + // + + bytesPerDeepLineTable (_ofd->header, + _lineBuffer->scanLineMin, + _lineBuffer->scanLineMax, + _ofd->sampleCountSliceBase, + _ofd->sampleCountXStride, + _ofd->sampleCountYStride, + _ofd->bytesPerLine); + for (int i = _lineBuffer->scanLineMin; i <= _lineBuffer->scanLineMax; i++) + { + // (TODO) don't do this all the time. + _lineBuffer->buffer[i - _lineBuffer->minY].resizeErase( + _ofd->bytesPerLine[i - _ofd->minY]); + + for (int j = _ofd->minX; j <= _ofd->maxX; j++) + _ofd->lineSampleCount[i - _ofd->minY] += _ofd->getSampleCount(j, i); + } + + // + // Copy data from frame buffer to line buffer. + // + + int y; + + for (y = yStart; y != yStop; y += dy) + { + // + // Gather one scan line's worth of pixel data and store + // them in _ofd->lineBuffer. + // + + char *writePtr = &_lineBuffer->buffer[y - _lineBuffer->minY][0]; + // + // Iterate over all image channels. + // + + for (unsigned int i = 0; i < _ofd->slices.size(); ++i) + { + // + // Test if scan line y of this channel contains any data + // (the scan line contains data only if y % ySampling == 0). + // + + const OutSliceInfo &slice = *_ofd->slices[i]; + + if (modp (y, slice.ySampling) != 0) + continue; + + // + // Fill the line buffer with with pixel data. + // + + if (slice.zero) + { + // + // The frame buffer contains no data for this channel. + // Store zeroes in _lineBuffer->buffer. + // + + fillChannelWithZeroes (writePtr, _ofd->format, slice.type, + _ofd->lineSampleCount[y - _ofd->minY]); + } + else + { + + copyFromDeepFrameBuffer (writePtr, slice.base, + _ofd->sampleCountSliceBase, + _ofd->sampleCountXStride, + _ofd->sampleCountYStride, + y, _ofd->minX, _ofd->maxX, + 0, 0,//offsets for samplecount + 0, 0,//offsets for data + slice.sampleStride, + slice.xStride, + slice.yStride, + _ofd->format, + slice.type); + } + } + } + + // + // If the next scanline isn't past the bounds of the lineBuffer + // then we have partially filled the linebuffer, + // otherwise the whole linebuffer is filled and then + // we compress the linebuffer and write it out. + // + + if (y >= _lineBuffer->minY && y <= _lineBuffer->maxY) + return; + + // + // Copy all data into a consecutive buffer. + // + + Int64 totalBytes = 0; + Int64 maxBytesPerLine = 0; + for (int i = 0; i < _lineBuffer->maxY - _lineBuffer->minY + 1; i++) + { + totalBytes += _lineBuffer->buffer[i].size(); + if (Int64(_lineBuffer->buffer[i].size()) > maxBytesPerLine) + maxBytesPerLine = _lineBuffer->buffer[i].size(); + } + _lineBuffer->consecutiveBuffer.resizeErase(totalBytes); + + int pos = 0; + for (int i = 0; i < _lineBuffer->maxY - _lineBuffer->minY + 1; i++) + { + memcpy(_lineBuffer->consecutiveBuffer + pos, + &_lineBuffer->buffer[i][0], + _lineBuffer->buffer[i].size()); + pos += _lineBuffer->buffer[i].size(); + } + + _lineBuffer->dataPtr = _lineBuffer->consecutiveBuffer; + + _lineBuffer->dataSize = totalBytes; + _lineBuffer->uncompressedDataSize = _lineBuffer->dataSize; + + // + // Compress the pixel sample count table. + // + + char* ptr = _lineBuffer->sampleCountTableBuffer; + Int64 tableDataSize = 0; + for (int i = _lineBuffer->minY; i <= _lineBuffer->maxY; i++) + { + int count = 0; + for (int j = _ofd->minX; j <= _ofd->maxX; j++) + { + count += _ofd->getSampleCount(j, i); + Xdr::write (ptr, count); + tableDataSize += sizeof (int); + } + } + + if(_lineBuffer->sampleCountTableCompressor) + { + _lineBuffer->sampleCountTableSize = + _lineBuffer->sampleCountTableCompressor->compress ( + _lineBuffer->sampleCountTableBuffer, + tableDataSize, + _lineBuffer->minY, + _lineBuffer->sampleCountTablePtr); + } + + // + // If we can't make data shrink (or we weren't compressing), then just use the raw data. + // + + if (!_lineBuffer->sampleCountTableCompressor || + _lineBuffer->sampleCountTableSize >= tableDataSize) + { + _lineBuffer->sampleCountTableSize = tableDataSize; + _lineBuffer->sampleCountTablePtr = _lineBuffer->sampleCountTableBuffer; + } + + // + // Compress the sample data + // + + // (TODO) don't do this all the time. + if (_lineBuffer->compressor != 0) + delete _lineBuffer->compressor; + _lineBuffer->compressor = newCompressor (_ofd->header.compression(), + maxBytesPerLine, + _ofd->header); + + Compressor *compressor = _lineBuffer->compressor; + + if (compressor) + { + const char *compPtr; + + Int64 compSize = compressor->compress (_lineBuffer->dataPtr, + _lineBuffer->dataSize, + _lineBuffer->minY, compPtr); + + if (compSize < _lineBuffer->dataSize) + { + _lineBuffer->dataSize = compSize; + _lineBuffer->dataPtr = compPtr; + } + else if (_ofd->format == Compressor::NATIVE) + { + // + // The data did not shrink during compression, but + // we cannot write to the file using the machine's + // native format, so we need to convert the lineBuffer + // to Xdr. + // + + convertToXdr (_ofd, _lineBuffer->consecutiveBuffer, _lineBuffer->minY, + _lineBuffer->maxY, _lineBuffer->dataSize); + } + } + + _lineBuffer->partiallyFull = false; + } + catch (std::exception &e) + { + if (!_lineBuffer->hasException) + { + _lineBuffer->exception = e.what (); + _lineBuffer->hasException = true; + } + } + catch (...) + { + if (!_lineBuffer->hasException) + { + _lineBuffer->exception = "unrecognized exception"; + _lineBuffer->hasException = true; + } + } +} + +} // namespace + + +DeepScanLineOutputFile::DeepScanLineOutputFile + (const char fileName[], + const Header &header, + int numThreads) +: + _data (new Data (numThreads)) +{ + _data->_streamData=new OutputStreamMutex (); + _data->_deleteStream=true; + try + { + header.sanityCheck(); + _data->_streamData->os = new StdOFStream (fileName); + initialize (header); + _data->_streamData->currentPosition = _data->_streamData->os->tellp(); + + // Write header and empty offset table to the file. + writeMagicNumberAndVersionField(*_data->_streamData->os, _data->header); + _data->previewPosition = + _data->header.writeTo (*_data->_streamData->os); + _data->lineOffsetsPosition = + writeLineOffsets (*_data->_streamData->os, _data->lineOffsets); + _data->multipart=false;// not multipart; only one header + } + catch (IEX_NAMESPACE::BaseExc &e) + { + delete _data->_streamData->os; + delete _data->_streamData; + delete _data; + + REPLACE_EXC (e, "Cannot open image file " + "\"" << fileName << "\". " << e.what()); + throw; + } + catch (...) + { + delete _data->_streamData->os; + delete _data->_streamData; + delete _data; + throw; + } +} + + +DeepScanLineOutputFile::DeepScanLineOutputFile + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + int numThreads) +: + _data (new Data (numThreads)) + +{ + _data->_streamData = new OutputStreamMutex (); + _data->_deleteStream = false; + try + { + header.sanityCheck(); + _data->_streamData->os = &os; + initialize (header); + _data->_streamData->currentPosition = _data->_streamData->os->tellp(); + + // Write header and empty offset table to the file. + writeMagicNumberAndVersionField(*_data->_streamData->os, _data->header); + _data->previewPosition = + _data->header.writeTo (*_data->_streamData->os); + _data->lineOffsetsPosition = + writeLineOffsets (*_data->_streamData->os, _data->lineOffsets); + _data->multipart=false; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + delete _data->_streamData; + delete _data; + + REPLACE_EXC (e, "Cannot open image file " + "\"" << os.fileName() << "\". " << e.what()); + throw; + } + catch (...) + { + delete _data->_streamData; + delete _data; + throw; + } +} + +DeepScanLineOutputFile::DeepScanLineOutputFile(const OutputPartData* part) +{ + try + { + if (part->header.type() != DEEPSCANLINE) + throw IEX_NAMESPACE::ArgExc("Can't build a DeepScanLineOutputFile from a type-mismatched part."); + + _data = new Data (part->numThreads); + _data->_streamData = part->mutex; + _data->_deleteStream=false; + initialize (part->header); + _data->partNumber = part->partNumber; + _data->lineOffsetsPosition = part->chunkOffsetTablePosition; + _data->previewPosition = part->previewPosition; + _data->multipart=part->multipart; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + delete _data; + + REPLACE_EXC (e, "Cannot initialize output part " + "\"" << part->partNumber << "\". " << e.what()); + throw; + } + catch (...) + { + delete _data; + throw; + } +} + +void +DeepScanLineOutputFile::initialize (const Header &header) +{ + _data->header = header; + + _data->header.setType(DEEPSCANLINE); + + const Box2i &dataWindow = header.dataWindow(); + + _data->currentScanLine = (header.lineOrder() == INCREASING_Y)? + dataWindow.min.y: dataWindow.max.y; + + _data->missingScanLines = dataWindow.max.y - dataWindow.min.y + 1; + _data->lineOrder = header.lineOrder(); + _data->minX = dataWindow.min.x; + _data->maxX = dataWindow.max.x; + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; + + _data->lineSampleCount.resizeErase(_data->maxY - _data->minY + 1); + + Compressor* compressor = newCompressor (_data->header.compression(), + 0, + _data->header); + _data->format = defaultFormat (compressor); + _data->linesInBuffer = numLinesInBuffer (compressor); + if (compressor != 0) + delete compressor; + + int lineOffsetSize = (_data->maxY - _data->minY + + _data->linesInBuffer) / _data->linesInBuffer; + + + _data->header.setChunkCount(lineOffsetSize); + + _data->lineOffsets.resize (lineOffsetSize); + + _data->bytesPerLine.resize (_data->maxY - _data->minY + 1); + + _data->maxSampleCountTableSize = min(_data->linesInBuffer, _data->maxY - _data->minY + 1) * + (_data->maxX - _data->minX + 1) * + sizeof(unsigned int); + + for (size_t i = 0; i < _data->lineBuffers.size(); ++i) + { + _data->lineBuffers[i] = new LineBuffer (_data->linesInBuffer); + _data->lineBuffers[i]->sampleCountTableBuffer.resizeErase(_data->maxSampleCountTableSize); + + _data->lineBuffers[i]->sampleCountTableCompressor = + newCompressor (_data->header.compression(), + _data->maxSampleCountTableSize, + _data->header); + } +} + + +DeepScanLineOutputFile::~DeepScanLineOutputFile () +{ + { + Lock lock(*_data->_streamData); + Int64 originalPosition = _data->_streamData->os->tellp(); + + if (_data->lineOffsetsPosition > 0) + { + try + { + _data->_streamData->os->seekp (_data->lineOffsetsPosition); + writeLineOffsets (*_data->_streamData->os, _data->lineOffsets); + + // + // Restore the original position. + // + _data->_streamData->os->seekp (originalPosition); + } + catch (...) + { + // + // We cannot safely throw any exceptions from here. + // This destructor may have been called because the + // stack is currently being unwound for another + // exception. + // + } + } + } + + if (_data->_deleteStream) + delete _data->_streamData->os; + + // + // (TODO) we should have a way to tell if the stream data is owned by this file or + // by a parent multipart file. + // + + if (_data->partNumber == -1) + delete _data->_streamData; + + delete _data; +} + + +const char * +DeepScanLineOutputFile::fileName () const +{ + return _data->_streamData->os->fileName(); +} + + +const Header & +DeepScanLineOutputFile::header () const +{ + return _data->header; +} + + +void +DeepScanLineOutputFile::setFrameBuffer (const DeepFrameBuffer &frameBuffer) +{ + Lock lock (*_data->_streamData); + + // + // Check if the new frame buffer descriptor + // is compatible with the image file header. + // + + const ChannelList &channels = _data->header.channels(); + + for (ChannelList::ConstIterator i = channels.begin(); + i != channels.end(); + ++i) + { + DeepFrameBuffer::ConstIterator j = frameBuffer.find (i.name()); + + if (j == frameBuffer.end()) + continue; + + if (i.channel().type != j.slice().type) + { + THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" channel " + "of output file \"" << fileName() << "\" is " + "not compatible with the frame buffer's " + "pixel type."); + } + + if (i.channel().xSampling != j.slice().xSampling || + i.channel().ySampling != j.slice().ySampling) + { + THROW (IEX_NAMESPACE::ArgExc, "X and/or y subsampling factors " + "of \"" << i.name() << "\" channel " + "of output file \"" << fileName() << "\" are " + "not compatible with the frame buffer's " + "subsampling factors."); + } + } + + // + // Store the pixel sample count table. + // (TODO) Support for different sampling rates? + // + + const Slice& sampleCountSlice = frameBuffer.getSampleCountSlice(); + if (sampleCountSlice.base == 0) + { + throw IEX_NAMESPACE::ArgExc ("Invalid base pointer, please set a proper sample count slice."); + } + else + { + _data->sampleCountSliceBase = sampleCountSlice.base; + _data->sampleCountXStride = sampleCountSlice.xStride; + _data->sampleCountYStride = sampleCountSlice.yStride; + } + + // + // Initialize slice table for writePixels(). + // Pixel sample count slice is not presented in the header, + // so it wouldn't be added here. + // Store the pixel base pointer table. + // (TODO) Support for different sampling rates? + // + + vector slices; + + for (ChannelList::ConstIterator i = channels.begin(); + i != channels.end(); + ++i) + { + DeepFrameBuffer::ConstIterator j = frameBuffer.find (i.name()); + + if (j == frameBuffer.end()) + { + // + // Channel i is not present in the frame buffer. + // In the file, channel i will contain only zeroes. + // + + slices.push_back (new OutSliceInfo (i.channel().type, + NULL,// base + 0,// sampleStride, + 0,// xStride + 0,// yStride + i.channel().xSampling, + i.channel().ySampling, + true)); // zero + } + else + { + // + // Channel i is present in the frame buffer. + // + + slices.push_back (new OutSliceInfo (j.slice().type, + j.slice().base, + j.slice().sampleStride, + j.slice().xStride, + j.slice().yStride, + j.slice().xSampling, + j.slice().ySampling, + false)); // zero + + } + } + + // + // Store the new frame buffer. + // + + _data->frameBuffer = frameBuffer; + + for (size_t i = 0; i < _data->slices.size(); i++) + delete _data->slices[i]; + _data->slices = slices; +} + + +const DeepFrameBuffer & +DeepScanLineOutputFile::frameBuffer () const +{ + Lock lock (*_data->_streamData); + return _data->frameBuffer; +} + + +void +DeepScanLineOutputFile::writePixels (int numScanLines) +{ + try + { + Lock lock (*_data->_streamData); + + if (_data->slices.size() == 0) + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data source."); + + // + // Maintain two iterators: + // nextWriteBuffer: next linebuffer to be written to the file + // nextCompressBuffer: next linebuffer to compress + // + + int first = (_data->currentScanLine - _data->minY) / + _data->linesInBuffer; + + int nextWriteBuffer = first; + int nextCompressBuffer; + int stop; + int step; + int scanLineMin; + int scanLineMax; + + { + // + // Create a task group for all line buffer tasks. When the + // taskgroup goes out of scope, the destructor waits until + // all tasks are complete. + // + + TaskGroup taskGroup; + + // + // Determine the range of lineBuffers that intersect the scan + // line range. Then add the initial compression tasks to the + // thread pool. We always add in at least one task but the + // individual task might not do anything if numScanLines == 0. + // + + if (_data->lineOrder == INCREASING_Y) + { + int last = (_data->currentScanLine + (numScanLines - 1) - + _data->minY) / _data->linesInBuffer; + + scanLineMin = _data->currentScanLine; + scanLineMax = _data->currentScanLine + numScanLines - 1; + + int numTasks = max (min ((int)_data->lineBuffers.size(), + last - first + 1), + 1); + + for (int i = 0; i < numTasks; i++) + { + ThreadPool::addGlobalTask + (new LineBufferTask (&taskGroup, _data, first + i, + scanLineMin, scanLineMax)); + } + + nextCompressBuffer = first + numTasks; + stop = last + 1; + step = 1; + } + else + { + int last = (_data->currentScanLine - (numScanLines - 1) - + _data->minY) / _data->linesInBuffer; + + scanLineMax = _data->currentScanLine; + scanLineMin = _data->currentScanLine - numScanLines + 1; + + int numTasks = max (min ((int)_data->lineBuffers.size(), + first - last + 1), + 1); + + for (int i = 0; i < numTasks; i++) + { + ThreadPool::addGlobalTask + (new LineBufferTask (&taskGroup, _data, first - i, + scanLineMin, scanLineMax)); + } + + nextCompressBuffer = first - numTasks; + stop = last - 1; + step = -1; + } + + while (true) + { + if (_data->missingScanLines <= 0) + { + throw IEX_NAMESPACE::ArgExc ("Tried to write more scan lines " + "than specified by the data window."); + } + + // + // Wait until the next line buffer is ready to be written + // + + LineBuffer *writeBuffer = + _data->getLineBuffer (nextWriteBuffer); + + writeBuffer->wait(); + + int numLines = writeBuffer->scanLineMax - + writeBuffer->scanLineMin + 1; + + _data->missingScanLines -= numLines; + + // + // If the line buffer is only partially full, then it is + // not complete and we cannot write it to disk yet. + // + + if (writeBuffer->partiallyFull) + { + _data->currentScanLine = _data->currentScanLine + + step * numLines; + writeBuffer->post(); + + return; + } + + // + // Write the line buffer + // + + writePixelData (_data->_streamData, _data, writeBuffer); + nextWriteBuffer += step; + + _data->currentScanLine = _data->currentScanLine + + step * numLines; + + #ifdef DEBUG + + assert (_data->currentScanLine == + ((_data->lineOrder == INCREASING_Y) ? + writeBuffer->scanLineMax + 1: + writeBuffer->scanLineMin - 1)); + + #endif + + // + // Release the lock on the line buffer + // + + writeBuffer->post(); + + // + // If this was the last line buffer in the scanline range + // + + if (nextWriteBuffer == stop) + break; + + // + // If there are no more line buffers to compress, + // then only continue to write out remaining lineBuffers + // + + if (nextCompressBuffer == stop) + continue; + + // + // Add nextCompressBuffer as a compression task + // + + ThreadPool::addGlobalTask + (new LineBufferTask (&taskGroup, _data, nextCompressBuffer, + scanLineMin, scanLineMax)); + + // + // Update the next line buffer we need to compress + // + + nextCompressBuffer += step; + } + + // + // Finish all tasks + // + } + + // + // Exeption handling: + // + // LineBufferTask::execute() may have encountered exceptions, but + // those exceptions occurred in another thread, not in the thread + // that is executing this call to OutputFile::writePixels(). + // LineBufferTask::execute() has caught all exceptions and stored + // the exceptions' what() strings in the line buffers. + // Now we check if any line buffer contains a stored exception; if + // this is the case then we re-throw the exception in this thread. + // (It is possible that multiple line buffers contain stored + // exceptions. We re-throw the first exception we find and + // ignore all others.) + // + + const string *exception = 0; + + for (size_t i = 0; i < _data->lineBuffers.size(); ++i) + { + LineBuffer *lineBuffer = _data->lineBuffers[i]; + + if (lineBuffer->hasException && !exception) + exception = &lineBuffer->exception; + + lineBuffer->hasException = false; + } + + if (exception) + throw IEX_NAMESPACE::IoExc (*exception); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Failed to write pixel data to image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +int +DeepScanLineOutputFile::currentScanLine () const +{ + Lock lock (*_data->_streamData); + return _data->currentScanLine; +} + + +void +DeepScanLineOutputFile::copyPixels (DeepScanLineInputPart &in) +{ + copyPixels(*in.file); +} + +void +DeepScanLineOutputFile::copyPixels (DeepScanLineInputFile &in) +{ + + Lock lock (*_data->_streamData); + + // + // Check if this file's and and the InputFile's + // headers are compatible. + // + + const Header &hdr = _data->header; + const Header &inHdr = in.header(); + + if(!inHdr.hasType() || inHdr.type()!=DEEPSCANLINE) + { + THROW (IEX_NAMESPACE::ArgExc, "Cannot copy pixels from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\": the input needs to be a deep scanline image"); + } + if (!(hdr.dataWindow() == inHdr.dataWindow())) + THROW (IEX_NAMESPACE::ArgExc, "Cannot copy pixels from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\". " + "The files have different data windows."); + + if (!(hdr.lineOrder() == inHdr.lineOrder())) + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files have different line orders."); + + if (!(hdr.compression() == inHdr.compression())) + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files use different compression methods."); + + if (!(hdr.channels() == inHdr.channels())) + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files have different channel lists."); + + // + // Verify that no pixel data have been written to this file yet. + // + + const Box2i &dataWindow = hdr.dataWindow(); + + if (_data->missingScanLines != dataWindow.max.y - dataWindow.min.y + 1) + THROW (IEX_NAMESPACE::LogicExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "\"" << fileName() << "\" already contains " + "pixel data."); + + // + // Copy the pixel data. + // + + vector data(4096); + + while (_data->missingScanLines > 0) + { + Int64 dataSize = (Int64) data.size(); + in.rawPixelData(_data->currentScanLine, &data[0], dataSize); + if(dataSize > data.size()) + { + // block wasn't big enough - go again with enough memory this time + data.resize(dataSize); + in.rawPixelData(_data->currentScanLine, &data[0], dataSize); + } + + // extract header from block to pass to writePixelData + + Int64 packedSampleCountSize = *(Int64 *) (&data[4]); + Int64 packedDataSize = *(Int64 *) (&data[12]); + Int64 unpackedDataSize = *(Int64 *) (&data[20]); + const char * sampleCountTable = &data[0]+28; + const char * pixelData = sampleCountTable + packedSampleCountSize; + + + writePixelData (_data->_streamData, _data, lineBufferMinY (_data->currentScanLine, + _data->minY, + _data->linesInBuffer), + pixelData, packedDataSize, unpackedDataSize,sampleCountTable,packedSampleCountSize); + + _data->currentScanLine += (_data->lineOrder == INCREASING_Y)? + _data->linesInBuffer: -_data->linesInBuffer; + + _data->missingScanLines -= _data->linesInBuffer; + } +} + + +void +DeepScanLineOutputFile::updatePreviewImage (const PreviewRgba newPixels[]) +{ + Lock lock (*_data->_streamData); + + if (_data->previewPosition <= 0) + THROW (IEX_NAMESPACE::LogicExc, "Cannot update preview image pixels. " + "File \"" << fileName() << "\" does not " + "contain a preview image."); + + // + // Store the new pixels in the header's preview image attribute. + // + + PreviewImageAttribute &pia = + _data->header.typedAttribute ("preview"); + + PreviewImage &pi = pia.value(); + PreviewRgba *pixels = pi.pixels(); + int numPixels = pi.width() * pi.height(); + + for (int i = 0; i < numPixels; ++i) + pixels[i] = newPixels[i]; + + // + // Save the current file position, jump to the position in + // the file where the preview image starts, store the new + // preview image, and jump back to the saved file position. + // + + Int64 savedPosition = _data->_streamData->os->tellp(); + + try + { + _data->_streamData->os->seekp (_data->previewPosition); + pia.writeValueTo (*_data->_streamData->os, _data->version); + _data->_streamData->os->seekp (savedPosition); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Cannot update preview image pixels for " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputFile.h b/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputFile.h new file mode 100644 index 0000000000..945b00d3b8 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputFile.h @@ -0,0 +1,256 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + + +#ifndef INCLUDED_IMF_DEEP_SCAN_LINE_OUTPUT_FILE_H +#define INCLUDED_IMF_DEEP_SCAN_LINE_OUTPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class DeepScanLineOutputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfThreading.h" +#include "ImfGenericOutputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +struct PreviewRgba; + +class DeepScanLineOutputFile : public GenericOutputFile +{ + public: + + //----------------------------------------------------------- + // Constructor -- opens the file and writes the file header. + // The file header is also copied into the DeepScanLineOutputFile + // object, and can later be accessed via the header() method. + // Destroying this DeepScanLineOutputFile object automatically closes + // the file. + // + // numThreads determines the number of threads that will be + // used to write the file (see ImfThreading.h). + //----------------------------------------------------------- + + IMF_EXPORT + DeepScanLineOutputFile (const char fileName[], const Header &header, + int numThreads = globalThreadCount()); + + + //------------------------------------------------------------ + // Constructor -- attaches the new DeepScanLineOutputFile object + // to a file that has already been opened, and writes the file header. + // The file header is also copied into the DeepScanLineOutputFile + // object, and can later be accessed via the header() method. + // Destroying this DeepScanLineOutputFile object does not automatically + // close the file. + // + // numThreads determines the number of threads that will be + // used to write the file (see ImfThreading.h). + //------------------------------------------------------------ + + IMF_EXPORT + DeepScanLineOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header, + int numThreads = globalThreadCount()); + + + //------------------------------------------------- + // Destructor + // + // Destroying the DeepScanLineOutputFile object + // before writing all scan lines within the data + // window results in an incomplete file. + //------------------------------------------------- + + IMF_EXPORT + virtual ~DeepScanLineOutputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + IMF_EXPORT + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + IMF_EXPORT + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the OutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writePixels() is + // called. The current frame buffer can be changed + // after each call to writePixels. + //------------------------------------------------------- + + IMF_EXPORT + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + IMF_EXPORT + const DeepFrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------------- + // Write pixel data: + // + // writePixels(n) retrieves the next n scan lines worth of data from + // the current frame buffer, starting with the scan line indicated by + // currentScanLine(), and stores the data in the output file, and + // progressing in the direction indicated by header.lineOrder(). + // + // To produce a complete and correct file, exactly m scan lines must + // be written, where m is equal to + // header().dataWindow().max.y - header().dataWindow().min.y + 1. + //------------------------------------------------------------------- + + IMF_EXPORT + void writePixels (int numScanLines = 1); + + + //------------------------------------------------------------------ + // Access to the current scan line: + // + // currentScanLine() returns the y coordinate of the first scan line + // that will be read from the current frame buffer during the next + // call to writePixels(). + // + // If header.lineOrder() == INCREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().min.y. After writing each scan line, + // the current scan line is incremented by 1. + // + // If header.lineOrder() == DECREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().max.y. After writing each scan line, + // the current scan line is decremented by 1. + // + //------------------------------------------------------------------ + + IMF_EXPORT + int currentScanLine () const; + + + //-------------------------------------------------------------- + // Shortcut to copy all pixels from an InputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the InputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder" and "channels" attributes must be the same. + //-------------------------------------------------------------- + + IMF_EXPORT + void copyPixels (DeepScanLineInputFile &in); + + // -------------------------------------------------------------- + // Shortcut to copy pixels from a given part of a multipart file + // -------------------------------------------------------------- + IMF_EXPORT + void copyPixels (DeepScanLineInputPart &in); + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few scan lines at a + // time, while the image is being generated. Since the preview + // image is an attribute in the file's header, it gets stored in + // the file as soon as the file is opened, but we may not know + // what the preview image should look like until we have written + // the last scan line of the main image. + // + //-------------------------------------------------------------- + + IMF_EXPORT + void updatePreviewImage (const PreviewRgba newPixels[]); + + + struct Data; + + private: + + //------------------------------------------------------------ + // Constructor -- attaches the OutputStreamMutex to the + // given one from MultiPartOutputFile. Set the previewPosition + // and lineOffsetsPosition which have been acquired from + // the constructor of MultiPartOutputFile as well. + //------------------------------------------------------------ + DeepScanLineOutputFile (const OutputPartData* part); + + DeepScanLineOutputFile (const DeepScanLineOutputFile &); // not implemented + DeepScanLineOutputFile & operator = (const DeepScanLineOutputFile &); // not implemented + + void initialize (const Header &header); + void initializeLineBuffer(); + + Data * _data; + + + + friend class MultiPartOutputFile; +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputPart.cpp b/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputPart.cpp new file mode 100644 index 0000000000..d7a44e8eb9 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputPart.cpp @@ -0,0 +1,107 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfDeepScanLineOutputPart.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +DeepScanLineOutputPart::DeepScanLineOutputPart(MultiPartOutputFile& multiPartFile, int partNumber) +{ + file = multiPartFile.getOutputPart(partNumber); +} + + +const char * +DeepScanLineOutputPart::fileName () const +{ + return file->fileName(); +} + + +const Header & +DeepScanLineOutputPart::header () const +{ + return file->header(); +} + + +void +DeepScanLineOutputPart::setFrameBuffer (const DeepFrameBuffer &frameBuffer) +{ + file->setFrameBuffer(frameBuffer); +} + + +const DeepFrameBuffer & +DeepScanLineOutputPart::frameBuffer () const +{ + return file->frameBuffer(); +} + + +void +DeepScanLineOutputPart::writePixels (int numScanLines) +{ + file->writePixels(numScanLines); +} + + +int +DeepScanLineOutputPart::currentScanLine () const +{ + return file->currentScanLine(); +} + + +void +DeepScanLineOutputPart::copyPixels (DeepScanLineInputFile &in) +{ + file->copyPixels(in); +} + +void +DeepScanLineOutputPart::copyPixels (DeepScanLineInputPart &in) +{ + file->copyPixels(in); +} + +void +DeepScanLineOutputPart::updatePreviewImage (const PreviewRgba newPixels[]) +{ + file->updatePreviewImage(newPixels); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT + diff --git a/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputPart.h b/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputPart.h new file mode 100644 index 0000000000..22faa2562a --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepScanLineOutputPart.h @@ -0,0 +1,178 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFDEEPSCANLINEOUTPUTPART_H_ +#define IMFDEEPSCANLINEOUTPUTPART_H_ + +#include "ImfDeepScanLineOutputFile.h" +#include "ImfMultiPartOutputFile.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class DeepScanLineOutputPart +{ + public: + + IMF_EXPORT + DeepScanLineOutputPart(MultiPartOutputFile& multiPartFile, int partNumber); + + //------------------------ + // Access to the file name + //------------------------ + + IMF_EXPORT + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + IMF_EXPORT + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the OutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writePixels() is + // called. The current frame buffer can be changed + // after each call to writePixels. + //------------------------------------------------------- + + IMF_EXPORT + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + IMF_EXPORT + const DeepFrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------------- + // Write pixel data: + // + // writePixels(n) retrieves the next n scan lines worth of data from + // the current frame buffer, starting with the scan line indicated by + // currentScanLine(), and stores the data in the output file, and + // progressing in the direction indicated by header.lineOrder(). + // + // To produce a complete and correct file, exactly m scan lines must + // be written, where m is equal to + // header().dataWindow().max.y - header().dataWindow().min.y + 1. + //------------------------------------------------------------------- + + IMF_EXPORT + void writePixels (int numScanLines = 1); + + + //------------------------------------------------------------------ + // Access to the current scan line: + // + // currentScanLine() returns the y coordinate of the first scan line + // that will be read from the current frame buffer during the next + // call to writePixels(). + // + // If header.lineOrder() == INCREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().min.y. After writing each scan line, + // the current scan line is incremented by 1. + // + // If header.lineOrder() == DECREASING_Y: + // + // The current scan line before the first call to writePixels() + // is header().dataWindow().max.y. After writing each scan line, + // the current scan line is decremented by 1. + // + //------------------------------------------------------------------ + + IMF_EXPORT + int currentScanLine () const; + + + //-------------------------------------------------------------- + // Shortcut to copy all pixels from an InputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the InputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder" and "channels" attributes must be the same. + //-------------------------------------------------------------- + + IMF_EXPORT + void copyPixels (DeepScanLineInputFile &in); + IMF_EXPORT + void copyPixels (DeepScanLineInputPart &in); + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few scan lines at a + // time, while the image is being generated. Since the preview + // image is an attribute in the file's header, it gets stored in + // the file as soon as the file is opened, but we may not know + // what the preview image should look like until we have written + // the last scan line of the main image. + // + //-------------------------------------------------------------- + + IMF_EXPORT + void updatePreviewImage (const PreviewRgba newPixels[]); + + private: + DeepScanLineOutputFile* file; +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif /* IMFDEEPSCANLINEOUTPUTPART_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfDeepTiledInputFile.cpp b/3rdparty/openexr/IlmImf/ImfDeepTiledInputFile.cpp new file mode 100644 index 0000000000..e34f606d95 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepTiledInputFile.cpp @@ -0,0 +1,1979 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +//----------------------------------------------------------------------------- +// +// class DeepTiledInputFile +// +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include "ImathBox.h" +#include +#include +#include +#include +#include +#include +#include +#include "IlmThreadPool.h" +#include "IlmThreadSemaphore.h" +#include "IlmThreadMutex.h" +#include "ImfInputStreamMutex.h" +#include "ImfInputPartData.h" +#include "ImathVec.h" +#include "Iex.h" +#include +#include +#include +#include +#include + +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::V2i; +using std::string; +using std::vector; +using std::min; +using std::max; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using ILMTHREAD_NAMESPACE::Semaphore; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; + +namespace { + +struct TInSliceInfo +{ + PixelType typeInFrameBuffer; + PixelType typeInFile; + char* pointerArrayBase; + size_t xStride; + size_t yStride; + ptrdiff_t sampleStride; + bool fill; + bool skip; + double fillValue; + int xTileCoords; + int yTileCoords; + + TInSliceInfo (PixelType typeInFrameBuffer = HALF, + char * base = NULL, + PixelType typeInFile = HALF, + size_t xStride = 0, + size_t yStride = 0, + ptrdiff_t sampleStride = 0, + bool fill = false, + bool skip = false, + double fillValue = 0.0, + int xTileCoords = 0, + int yTileCoords = 0); +}; + + +TInSliceInfo::TInSliceInfo (PixelType tifb, + char * b, + PixelType tifl, + size_t xs, size_t ys, + ptrdiff_t spst, + bool f, bool s, + double fv, + int xtc, + int ytc) +: + typeInFrameBuffer (tifb), + typeInFile (tifl), + pointerArrayBase (b), + xStride (xs), + yStride (ys), + sampleStride (spst), + fill (f), + skip (s), + fillValue (fv), + xTileCoords (xtc), + yTileCoords (ytc) +{ + // empty +} + + +struct TileBuffer +{ + Array2D sampleCount; + const char * uncompressedData; + char * buffer; + Int64 dataSize; + Int64 uncompressedDataSize; + Compressor * compressor; + Compressor::Format format; + int dx; + int dy; + int lx; + int ly; + bool hasException; + string exception; + + TileBuffer (); + ~TileBuffer (); + + inline void wait () {_sem.wait();} + inline void post () {_sem.post();} + + protected: + + Semaphore _sem; +}; + + +TileBuffer::TileBuffer (): + uncompressedData (0), + buffer (0), + dataSize (0), + compressor (0), + format (defaultFormat (compressor)), + dx (-1), + dy (-1), + lx (-1), + ly (-1), + hasException (false), + exception (), + _sem (1) +{ + // empty +} + + +TileBuffer::~TileBuffer () +{ + delete compressor; +} + +} // namespace + + +class MultiPartInputFile; + + +// +// struct TiledInputFile::Data stores things that will be +// needed between calls to readTile() +// + +struct DeepTiledInputFile::Data: public Mutex +{ + Header header; // the image header + TileDescription tileDesc; // describes the tile layout + int version; // file's version + DeepFrameBuffer frameBuffer; // framebuffer to write into + LineOrder lineOrder; // the file's lineorder + int minX; // data window's min x coord + int maxX; // data window's max x coord + int minY; // data window's min y coord + int maxY; // data window's max x coord + + int numXLevels; // number of x levels + int numYLevels; // number of y levels + int * numXTiles; // number of x tiles at a level + int * numYTiles; // number of y tiles at a level + + TileOffsets tileOffsets; // stores offsets in file for + // each tile + + bool fileIsComplete; // True if no tiles are missing + // in the file + + vector slices; // info about channels in file + + // ourselves? or does someone + // else do it? + + int partNumber; // part number + + bool multiPartBackwardSupport; // if we are reading a multipart file + // using OpenEXR 1.7 API + + int numThreads; // number of threads + + MultiPartInputFile* multiPartFile; // the MultiPartInputFile used to + // support backward compatibility + + vector tileBuffers; // each holds a single tile + + bool memoryMapped; // if the stream is memory mapped + + char* sampleCountSliceBase; // pointer to the start of + // the sample count array + ptrdiff_t sampleCountXStride; // x stride of the sample count array + ptrdiff_t sampleCountYStride; // y stride of the sample count array + + int sampleCountXTileCoords; // the value of xTileCoords from the + // sample count slice + int sampleCountYTileCoords; // the value of yTileCoords from the + // sample count slice + + Array sampleCountTableBuffer; // the buffer for sample count table + + Compressor* sampleCountTableComp; // the decompressor for sample count table + + Int64 maxSampleCountTableSize; // the max size in bytes for a pixel + // sample count table + int combinedSampleSize; // total size of all channels combined to check sampletable size + + InputStreamMutex * _streamData; + bool _deleteStream; // should we delete the stream + Data (int numThreads); + ~Data (); + + inline TileBuffer * getTileBuffer (int number); + // hash function from tile indices + // into our vector of tile buffers + + int& getSampleCount(int x, int y); + // get the number of samples + // in each pixel +}; + + +DeepTiledInputFile::Data::Data (int numThreads): + numXTiles (0), + numYTiles (0), + partNumber (-1), + multiPartBackwardSupport(false), + numThreads(numThreads), + memoryMapped(false), + _streamData(NULL), + _deleteStream(false) +{ + // + // We need at least one tileBuffer, but if threading is used, + // to keep n threads busy we need 2*n tileBuffers + // + + tileBuffers.resize (max (1, 2 * numThreads)); +} + + +DeepTiledInputFile::Data::~Data () +{ + delete [] numXTiles; + delete [] numYTiles; + + for (size_t i = 0; i < tileBuffers.size(); i++) + delete tileBuffers[i]; + + if (multiPartBackwardSupport) + delete multiPartFile; + + for (size_t i = 0; i < slices.size(); i++) + delete slices[i]; +} + + +TileBuffer* +DeepTiledInputFile::Data::getTileBuffer (int number) +{ + return tileBuffers[number % tileBuffers.size()]; +} + + +int& +DeepTiledInputFile::Data::getSampleCount(int x, int y) +{ + return sampleCount(sampleCountSliceBase, + sampleCountXStride, + sampleCountYStride, + x, y); +} + + +namespace { + +void +readTileData (InputStreamMutex *streamData, + DeepTiledInputFile::Data *ifd, + int dx, int dy, + int lx, int ly, + char *&buffer, + Int64 &dataSize, + Int64 &unpackedDataSize) +{ + // + // Read a single tile block from the file and into the array pointed + // to by buffer. If the file is memory-mapped, then we change where + // buffer points instead of writing into the array (hence buffer needs + // to be a reference to a char *). + // + + // + // Look up the location for this tile in the Index and + // seek to that position if necessary + // + + Int64 tileOffset = ifd->tileOffsets (dx, dy, lx, ly); + + if (tileOffset == 0) + { + THROW (IEX_NAMESPACE::InputExc, "Tile (" << dx << ", " << dy << ", " << + lx << ", " << ly << ") is missing."); + } + + // + // In a multi-part file, the next chunk does not need to + // belong to the same part, so we have to compare the + // offset here. + // + + if ( !isMultiPart(ifd->version) ) + { + if (streamData->currentPosition != tileOffset) + streamData->is->seekg(tileOffset); + } + else + { + // + // In a multi-part file, the file pointer may be moved by other + // parts, so we have to ask tellg() where we are. + // + if (streamData->is->tellg() != tileOffset) + streamData->is->seekg (tileOffset); + } + + // + // Read the first few bytes of the tile (the header). + // Verify that the tile coordinates and the level number + // are correct. + // + + int tileXCoord, tileYCoord, levelX, levelY; + + if (isMultiPart(ifd->version)) + { + int partNumber; + Xdr::read (*streamData->is, partNumber); + if (partNumber != ifd->partNumber) + { + THROW (IEX_NAMESPACE::ArgExc, "Unexpected part number " << partNumber + << ", should be " << ifd->partNumber << "."); + } + } + + Xdr::read (*streamData->is, tileXCoord); + Xdr::read (*streamData->is, tileYCoord); + Xdr::read (*streamData->is, levelX); + Xdr::read (*streamData->is, levelY); + + Int64 tableSize; + Xdr::read (*streamData->is, tableSize); + + Xdr::read (*streamData->is, dataSize); + Xdr::read (*streamData->is, unpackedDataSize); + + + // + // Skip the pixel sample count table because we have read this data. + // + + Xdr::skip (*streamData->is, tableSize); + + + if (tileXCoord != dx) + throw IEX_NAMESPACE::InputExc ("Unexpected tile x coordinate."); + + if (tileYCoord != dy) + throw IEX_NAMESPACE::InputExc ("Unexpected tile y coordinate."); + + if (levelX != lx) + throw IEX_NAMESPACE::InputExc ("Unexpected tile x level number coordinate."); + + if (levelY != ly) + throw IEX_NAMESPACE::InputExc ("Unexpected tile y level number coordinate."); + + // + // Read the pixel data. + // + + if (streamData->is->isMemoryMapped ()) + buffer = streamData->is->readMemoryMapped (dataSize); + else + { + // (TODO) check if the packed data size is too big? + // (TODO) better memory management here. Don't delete buffer everytime. + if (buffer != 0) delete[] buffer; + buffer = new char[dataSize]; + streamData->is->read (buffer, dataSize); + } + + // + // Keep track of which tile is the next one in + // the file, so that we can avoid redundant seekg() + // operations (seekg() can be fairly expensive). + // + + streamData->currentPosition = tileOffset + 4 * Xdr::size() + + 3 * Xdr::size() + + tableSize + + dataSize; +} + + +void +readNextTileData (InputStreamMutex *streamData, + DeepTiledInputFile::Data *ifd, + int &dx, int &dy, + int &lx, int &ly, + char * & buffer, + Int64 &dataSize, + Int64 &unpackedDataSize) +{ + // + // Read the next tile block from the file + // + + // + // Read the first few bytes of the tile (the header). + // + + Xdr::read (*streamData->is, dx); + Xdr::read (*streamData->is, dy); + Xdr::read (*streamData->is, lx); + Xdr::read (*streamData->is, ly); + + Int64 tableSize; + Xdr::read (*streamData->is, tableSize); + + Xdr::read (*streamData->is, dataSize); + Xdr::read (*streamData->is, unpackedDataSize); + + // + // Skip the pixel sample count table because we have read this data. + // + + Xdr::skip (*streamData->is, tableSize); + + // + // Read the pixel data. + // + + streamData->is->read (buffer, dataSize); + + // + // Keep track of which tile is the next one in + // the file, so that we can avoid redundant seekg() + // operations (seekg() can be fairly expensive). + // + + streamData->currentPosition += 4 * Xdr::size() + + 3 * Xdr::size() + + tableSize + + dataSize; +} + + +// +// A TileBufferTask encapsulates the task of uncompressing +// a single tile and copying it into the frame buffer. +// + +class TileBufferTask : public Task +{ + public: + + TileBufferTask (TaskGroup *group, + DeepTiledInputFile::Data *ifd, + TileBuffer *tileBuffer); + + virtual ~TileBufferTask (); + + virtual void execute (); + + private: + + DeepTiledInputFile::Data * _ifd; + TileBuffer * _tileBuffer; +}; + + +TileBufferTask::TileBufferTask + (TaskGroup *group, + DeepTiledInputFile::Data *ifd, + TileBuffer *tileBuffer) +: + Task (group), + _ifd (ifd), + _tileBuffer (tileBuffer) +{ + // empty +} + + +TileBufferTask::~TileBufferTask () +{ + // + // Signal that the tile buffer is now free + // + + _tileBuffer->post (); +} + + +void +TileBufferTask::execute () +{ + try + { + // + // Calculate information about the tile + // + + Box2i tileRange = OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile ( + _ifd->tileDesc, + _ifd->minX, _ifd->maxX, + _ifd->minY, _ifd->maxY, + _tileBuffer->dx, + _tileBuffer->dy, + _tileBuffer->lx, + _tileBuffer->ly); + + // + // Get the size of the tile. + // + + Array numPixelsPerScanLine; + numPixelsPerScanLine.resizeErase(tileRange.max.y - tileRange.min.y + 1); + + int sizeOfTile = 0; + int maxBytesPerTileLine = 0; + + for (int y = tileRange.min.y; y <= tileRange.max.y; y++) + { + numPixelsPerScanLine[y - tileRange.min.y] = 0; + + int bytesPerLine = 0; + + for (int x = tileRange.min.x; x <= tileRange.max.x; x++) + { + int xOffset = _ifd->sampleCountXTileCoords * tileRange.min.x; + int yOffset = _ifd->sampleCountYTileCoords * tileRange.min.y; + + int count = _ifd->getSampleCount(x - xOffset, y - yOffset); + for (unsigned int c = 0; c < _ifd->slices.size(); ++c) + { + sizeOfTile += count * pixelTypeSize(_ifd->slices[c]->typeInFile); + bytesPerLine += count * pixelTypeSize(_ifd->slices[c]->typeInFile); + } + numPixelsPerScanLine[y - tileRange.min.y] += count; + } + + if (bytesPerLine > maxBytesPerTileLine) + maxBytesPerTileLine = bytesPerLine; + } + + // (TODO) don't do this every time. + if (_tileBuffer->compressor != 0) + delete _tileBuffer->compressor; + _tileBuffer->compressor = newTileCompressor + (_ifd->header.compression(), + maxBytesPerTileLine, + _ifd->tileDesc.ySize, + _ifd->header); + + // + // Uncompress the data, if necessary + // + + if (_tileBuffer->compressor && _tileBuffer->dataSize < Int64(sizeOfTile)) + { + _tileBuffer->format = _tileBuffer->compressor->format(); + + _tileBuffer->dataSize = _tileBuffer->compressor->uncompressTile + (_tileBuffer->buffer, _tileBuffer->dataSize, + tileRange, _tileBuffer->uncompressedData); + } + else + { + // + // If the line is uncompressed, it's in XDR format, + // regardless of the compressor's output format. + // + + _tileBuffer->format = Compressor::XDR; + _tileBuffer->uncompressedData = _tileBuffer->buffer; + } + + // + // Convert the tile of pixel data back from the machine-independent + // representation, and store the result in the frame buffer. + // + + const char *readPtr = _tileBuffer->uncompressedData; + // points to where we + // read from in the + // tile block + + // + // Iterate over the scan lines in the tile. + // + + for (int y = tileRange.min.y; y <= tileRange.max.y; ++y) + { + // + // Iterate over all image channels. + // + + for (unsigned int i = 0; i < _ifd->slices.size(); ++i) + { + TInSliceInfo &slice = *_ifd->slices[i]; + + // + // These offsets are used to facilitate both + // absolute and tile-relative pixel coordinates. + // + + int xOffsetForData = (slice.xTileCoords == 0) ? 0 : tileRange.min.x; + int yOffsetForData = (slice.yTileCoords == 0) ? 0 : tileRange.min.y; + int xOffsetForSampleCount = + (_ifd->sampleCountXTileCoords == 0) ? 0 : tileRange.min.x; + int yOffsetForSampleCount = + (_ifd->sampleCountYTileCoords == 0) ? 0 : tileRange.min.y; + + // + // Fill the frame buffer with pixel data. + // + + if (slice.skip) + { + // + // The file contains data for this channel, but + // the frame buffer contains no slice for this channel. + // + + skipChannel (readPtr, slice.typeInFile, + numPixelsPerScanLine[y - tileRange.min.y]); + } + else + { + // + // The frame buffer contains a slice for this channel. + // + + copyIntoDeepFrameBuffer (readPtr, slice.pointerArrayBase, + _ifd->sampleCountSliceBase, + _ifd->sampleCountXStride, + _ifd->sampleCountYStride, + y, + tileRange.min.x, + tileRange.max.x, + xOffsetForSampleCount, yOffsetForSampleCount, + xOffsetForData, yOffsetForData, + slice.sampleStride, + slice.xStride, + slice.yStride, + slice.fill, + slice.fillValue, _tileBuffer->format, + slice.typeInFrameBuffer, + slice.typeInFile); + } + } + } + } + catch (std::exception &e) + { + if (!_tileBuffer->hasException) + { + _tileBuffer->exception = e.what (); + _tileBuffer->hasException = true; + } + } + catch (...) + { + if (!_tileBuffer->hasException) + { + _tileBuffer->exception = "unrecognized exception"; + _tileBuffer->hasException = true; + } + } +} + + +TileBufferTask * +newTileBufferTask + (TaskGroup *group, + DeepTiledInputFile::Data *ifd, + int number, + int dx, int dy, + int lx, int ly) +{ + // + // Wait for a tile buffer to become available, + // fill the buffer with raw data from the file, + // and create a new TileBufferTask whose execute() + // method will uncompress the tile and copy the + // tile's pixels into the frame buffer. + // + + TileBuffer *tileBuffer = ifd->getTileBuffer (number); + + try + { + tileBuffer->wait(); + + tileBuffer->dx = dx; + tileBuffer->dy = dy; + tileBuffer->lx = lx; + tileBuffer->ly = ly; + + tileBuffer->uncompressedData = 0; + + readTileData (ifd->_streamData, ifd, dx, dy, lx, ly, + tileBuffer->buffer, + tileBuffer->dataSize, + tileBuffer->uncompressedDataSize); + } + catch (...) + { + // + // Reading from the file caused an exception. + // Signal that the tile buffer is free, and + // re-throw the exception. + // + + tileBuffer->post(); + throw; + } + + return new TileBufferTask (group, ifd, tileBuffer); +} + + +} // namespace + + +DeepTiledInputFile::DeepTiledInputFile (const char fileName[], int numThreads): + _data (new Data (numThreads)) +{ + _data->_deleteStream=true; + // + // This constructor is called when a user + // explicitly wants to read a tiled file. + // + + IStream* is = 0; + try + { + is = new StdIFStream (fileName); + readMagicNumberAndVersionField(*is, _data->version); + + // + // Compatibility to read multpart file. + // + if (isMultiPart(_data->version)) + { + compatibilityInitialize(*is); + } + else + { + _data->_streamData = new InputStreamMutex(); + _data->_streamData->is = is; + _data->header.readFrom (*_data->_streamData->is, _data->version); + initialize(); + _data->tileOffsets.readFrom (*(_data->_streamData->is), _data->fileIsComplete,false,true); + _data->_streamData->currentPosition = _data->_streamData->is->tellg(); + } + } + catch (IEX_NAMESPACE::BaseExc &e) + { + if (is) delete is; + if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + REPLACE_EXC (e, "Cannot open image file " + "\"" << fileName << "\". " << e.what()); + throw; + } + catch (...) + { + if (is) delete is; + if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + throw; + } +} + + +DeepTiledInputFile::DeepTiledInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads): + _data (new Data (numThreads)) +{ + _data->_streamData=0; + _data->_deleteStream=false; + + // + // This constructor is called when a user + // explicitly wants to read a tiled file. + // + + try + { + readMagicNumberAndVersionField(is, _data->version); + + // + // Backward compatibility to read multpart file. + // + if (isMultiPart(_data->version)) + { + compatibilityInitialize(is); + } + else + { + _data->_streamData = new InputStreamMutex(); + _data->_streamData->is = &is; + _data->header.readFrom (*_data->_streamData->is, _data->version); + initialize(); + // file is guaranteed not to be multipart, but is deep + _data->tileOffsets.readFrom (*(_data->_streamData->is), _data->fileIsComplete, false,true); + _data->memoryMapped = _data->_streamData->is->isMemoryMapped(); + _data->_streamData->currentPosition = _data->_streamData->is->tellg(); + } + } + catch (IEX_NAMESPACE::BaseExc &e) + { + if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + REPLACE_EXC (e, "Cannot open image file " + "\"" << is.fileName() << "\". " << e.what()); + throw; + } + catch (...) + { + if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + throw; + } +} + + +DeepTiledInputFile::DeepTiledInputFile (const Header &header, + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, + int version, + int numThreads) : + _data (new Data (numThreads)) + +{ + _data->_streamData->is = is; + _data->_deleteStream=false; + + // + // This constructor called by class Imf::InputFile + // when a user wants to just read an image file, and + // doesn't care or know if the file is tiled. + // No need to have backward compatibility here, because + // we have the header. + // + + _data->header = header; + _data->version = version; + initialize(); + _data->tileOffsets.readFrom (*(_data->_streamData->is), _data->fileIsComplete,false,true); + _data->memoryMapped = is->isMemoryMapped(); + _data->_streamData->currentPosition = _data->_streamData->is->tellg(); +} + + +DeepTiledInputFile::DeepTiledInputFile (InputPartData* part) : + _data (new Data (part->numThreads)) +{ + _data->_deleteStream=false; + multiPartInitialize(part); +} + + +void +DeepTiledInputFile::compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is) +{ + is.seekg(0); + // + // Construct a MultiPartInputFile, initialize TiledInputFile + // with the part 0 data. + // (TODO) maybe change the third parameter of the constructor of MultiPartInputFile later. + // + _data->multiPartFile = new MultiPartInputFile(is, _data->numThreads); + _data->multiPartBackwardSupport = true; + InputPartData* part = _data->multiPartFile->getPart(0); + + multiPartInitialize(part); +} + + +void +DeepTiledInputFile::multiPartInitialize(InputPartData* part) +{ + if (isTiled(part->header.type()) == false) + THROW (IEX_NAMESPACE::ArgExc, "Can't build a DeepTiledInputFile from a part of type " << part->header.type()); + + _data->_streamData = part->mutex; + _data->header = part->header; + _data->version = part->version; + _data->partNumber = part->partNumber; + _data->memoryMapped = _data->_streamData->is->isMemoryMapped(); + initialize(); + _data->tileOffsets.readFrom(part->chunkOffsets , _data->fileIsComplete); + _data->_streamData->currentPosition = _data->_streamData->is->tellg(); +} + + +void +DeepTiledInputFile::initialize () +{ + if (_data->partNumber == -1) + if (_data->header.type() != DEEPTILE) + throw IEX_NAMESPACE::ArgExc ("Expected a deep tiled file but the file is not deep tiled."); + if(_data->header.version()!=1) + { + THROW(IEX_NAMESPACE::ArgExc, "Version " << _data->header.version() << " not supported for deeptiled images in this version of the library"); + } + + _data->header.sanityCheck (true); + + _data->tileDesc = _data->header.tileDescription(); + _data->lineOrder = _data->header.lineOrder(); + + // + // Save the dataWindow information + // + + const Box2i &dataWindow = _data->header.dataWindow(); + _data->minX = dataWindow.min.x; + _data->maxX = dataWindow.max.x; + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; + + // + // Precompute level and tile information to speed up utility functions + // + + precalculateTileInfo (_data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + _data->numXTiles, _data->numYTiles, + _data->numXLevels, _data->numYLevels); + + // + // Create all the TileBuffers and allocate their internal buffers + // + + _data->tileOffsets = TileOffsets (_data->tileDesc.mode, + _data->numXLevels, + _data->numYLevels, + _data->numXTiles, + _data->numYTiles); + + for (size_t i = 0; i < _data->tileBuffers.size(); i++) + _data->tileBuffers[i] = new TileBuffer (); + + _data->maxSampleCountTableSize = _data->tileDesc.ySize * + _data->tileDesc.xSize * + sizeof(int); + + _data->sampleCountTableBuffer.resizeErase(_data->maxSampleCountTableSize); + + _data->sampleCountTableComp = newCompressor(_data->header.compression(), + _data->maxSampleCountTableSize, + _data->header); + + + const ChannelList & c=_data->header.channels(); + _data->combinedSampleSize=0; + for(ChannelList::ConstIterator i=c.begin();i!=c.end();i++) + { + switch( i.channel().type ) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF : + _data->combinedSampleSize+=Xdr::size(); + break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT : + _data->combinedSampleSize+=Xdr::size(); + break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT : + _data->combinedSampleSize+=Xdr::size(); + break; + default : + THROW(IEX_NAMESPACE::ArgExc, "Bad type for channel " << i.name() << " initializing deepscanline reader"); + } + } + +} + + +DeepTiledInputFile::~DeepTiledInputFile () +{ + if (!_data->memoryMapped) + for (size_t i = 0; i < _data->tileBuffers.size(); i++) + if (_data->tileBuffers[i]->buffer != 0) + delete [] _data->tileBuffers[i]->buffer; + + if (_data->_deleteStream) + delete _data->_streamData->is; + + // + // (TODO) we should have a way to tell if the stream data is owned by this file or + // by a parent multipart file. + // + + if (_data->partNumber == -1) + delete _data->_streamData; + + delete _data; +} + + +const char * +DeepTiledInputFile::fileName () const +{ + return _data->_streamData->is->fileName(); +} + + +const Header & +DeepTiledInputFile::header () const +{ + return _data->header; +} + + +int +DeepTiledInputFile::version () const +{ + return _data->version; +} + + +void +DeepTiledInputFile::setFrameBuffer (const DeepFrameBuffer &frameBuffer) +{ + Lock lock (*_data->_streamData); + + // + // Set the frame buffer + // + + // + // Check if the new frame buffer descriptor is + // compatible with the image file header. + // + + const ChannelList &channels = _data->header.channels(); + + for (DeepFrameBuffer::ConstIterator j = frameBuffer.begin(); + j != frameBuffer.end(); + ++j) + { + ChannelList::ConstIterator i = channels.find (j.name()); + + if (i == channels.end()) + continue; + + if (i.channel().xSampling != j.slice().xSampling || + i.channel().ySampling != j.slice().ySampling) + THROW (IEX_NAMESPACE::ArgExc, "X and/or y subsampling factors " + "of \"" << i.name() << "\" channel " + "of input file \"" << fileName() << "\" are " + "not compatible with the frame buffer's " + "subsampling factors."); + } + + // + // Store the pixel sample count table. + // (TODO) Support for different sampling rates? + // + + const Slice& sampleCountSlice = frameBuffer.getSampleCountSlice(); + if (sampleCountSlice.base == 0) + { + throw IEX_NAMESPACE::ArgExc ("Invalid base pointer, please set a proper sample count slice."); + } + else + { + _data->sampleCountSliceBase = sampleCountSlice.base; + _data->sampleCountXStride = sampleCountSlice.xStride; + _data->sampleCountYStride = sampleCountSlice.yStride; + _data->sampleCountXTileCoords = sampleCountSlice.xTileCoords; + _data->sampleCountYTileCoords = sampleCountSlice.yTileCoords; + } + + // + // Initialize the slice table for readPixels(). + // + + vector slices; + ChannelList::ConstIterator i = channels.begin(); + + for (DeepFrameBuffer::ConstIterator j = frameBuffer.begin(); + j != frameBuffer.end(); + ++j) + { + while (i != channels.end() && strcmp (i.name(), j.name()) < 0) + { + // + // Channel i is present in the file but not + // in the frame buffer; data for channel i + // will be skipped during readPixels(). + // + + slices.push_back (new TInSliceInfo (i.channel().type, + NULL, + i.channel().type, + 0, // xStride + 0, // yStride + 0, // sampleStride + false, // fill + true, // skip + 0.0)); // fillValue + ++i; + } + + bool fill = false; + + if (i == channels.end() || strcmp (i.name(), j.name()) > 0) + { + // + // Channel i is present in the frame buffer, but not in the file. + // In the frame buffer, slice j will be filled with a default value. + // + + fill = true; + } + + slices.push_back (new TInSliceInfo (j.slice().type, + j.slice().base, + fill? j.slice().type: i.channel().type, + j.slice().xStride, + j.slice().yStride, + j.slice().sampleStride, + fill, + false, // skip + j.slice().fillValue, + (j.slice().xTileCoords)? 1: 0, + (j.slice().yTileCoords)? 1: 0)); + + + if (i != channels.end() && !fill) + ++i; + } + + // (TODO) inspect the following code. It's additional to the scanline input file. + // Is this needed? + + while (i != channels.end()) + { + // + // Channel i is present in the file but not + // in the frame buffer; data for channel i + // will be skipped during readPixels(). + // + + slices.push_back (new TInSliceInfo (i.channel().type, + NULL, + i.channel().type, + 0, // xStride + 0, // yStride + 0, // sampleStride + false, // fill + true, // skip + 0.0)); // fillValue + ++i; + } + + // + // Store the new frame buffer. + // + + _data->frameBuffer = frameBuffer; + + for (size_t i = 0; i < _data->slices.size(); i++) + delete _data->slices[i]; + _data->slices = slices; +} + + +const DeepFrameBuffer & +DeepTiledInputFile::frameBuffer () const +{ + Lock lock (*_data->_streamData); + return _data->frameBuffer; +} + + +bool +DeepTiledInputFile::isComplete () const +{ + return _data->fileIsComplete; +} + + +void +DeepTiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly) +{ + // + // Read a range of tiles from the file into the framebuffer + // + + try + { + Lock lock (*_data->_streamData); + + if (_data->slices.size() == 0) + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data destination."); + + if (!isValidLevel (lx, ly)) + THROW (IEX_NAMESPACE::ArgExc, + "Level coordinate " + "(" << lx << ", " << ly << ") " + "is invalid."); + + // + // Determine the first and last tile coordinates in both dimensions. + // We always attempt to read the range of tiles in the order that + // they are stored in the file. + // + + if (dx1 > dx2) + std::swap (dx1, dx2); + + if (dy1 > dy2) + std::swap (dy1, dy2); + + int dyStart = dy1; + int dyStop = dy2 + 1; + int dY = 1; + + if (_data->lineOrder == DECREASING_Y) + { + dyStart = dy2; + dyStop = dy1 - 1; + dY = -1; + } + + // + // Create a task group for all tile buffer tasks. When the + // task group goes out of scope, the destructor waits until + // all tasks are complete. + // + + { + TaskGroup taskGroup; + int tileNumber = 0; + + for (int dy = dyStart; dy != dyStop; dy += dY) + { + for (int dx = dx1; dx <= dx2; dx++) + { + if (!isValidTile (dx, dy, lx, ly)) + THROW (IEX_NAMESPACE::ArgExc, + "Tile (" << dx << ", " << dy << ", " << + lx << "," << ly << ") is not a valid tile."); + + ThreadPool::addGlobalTask (newTileBufferTask (&taskGroup, + _data, + tileNumber++, + dx, dy, + lx, ly)); + } + } + + // + // finish all tasks + // + } + + // + // Exeption handling: + // + // TileBufferTask::execute() may have encountered exceptions, but + // those exceptions occurred in another thread, not in the thread + // that is executing this call to TiledInputFile::readTiles(). + // TileBufferTask::execute() has caught all exceptions and stored + // the exceptions' what() strings in the tile buffers. + // Now we check if any tile buffer contains a stored exception; if + // this is the case then we re-throw the exception in this thread. + // (It is possible that multiple tile buffers contain stored + // exceptions. We re-throw the first exception we find and + // ignore all others.) + // + + const string *exception = 0; + + for (size_t i = 0; i < _data->tileBuffers.size(); ++i) + { + TileBuffer *tileBuffer = _data->tileBuffers[i]; + + if (tileBuffer->hasException && !exception) + exception = &tileBuffer->exception; + + tileBuffer->hasException = false; + } + + if (exception) + throw IEX_NAMESPACE::IoExc (*exception); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error reading pixel data from image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +void +DeepTiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int l) +{ + readTiles (dx1, dx2, dy1, dy2, l, l); +} + + +void +DeepTiledInputFile::readTile (int dx, int dy, int lx, int ly) +{ + readTiles (dx, dx, dy, dy, lx, ly); +} + + +void +DeepTiledInputFile::readTile (int dx, int dy, int l) +{ + readTile (dx, dy, l, l); +} + + +void +DeepTiledInputFile::rawTileData (int &dx, int &dy, + int &lx, int &ly, + char * pixelData, + Int64 &pixelDataSize) const +{ + if (!isValidTile (dx, dy, lx, ly)) + throw IEX_NAMESPACE::ArgExc ("Tried to read a tile outside " + "the image file's data window."); + + Int64 tileOffset = _data->tileOffsets (dx, dy, lx, ly); + + if(tileOffset == 0) + { + THROW (IEX_NAMESPACE::InputExc, "Tile (" << dx << ", " << dy << ", " << + lx << ", " << ly << ") is missing."); + } + + Lock lock(*_data->_streamData); + + if (_data->_streamData->is->tellg() != tileOffset) + _data->_streamData->is->seekg (tileOffset); + + + // + // Read the first few bytes of the tile (the header). + // Verify that the tile coordinates and the level number + // are correct. + // + + int tileXCoord, tileYCoord, levelX, levelY; + + if (isMultiPart(_data->version)) + { + int partNumber; + Xdr::read (*_data->_streamData->is, partNumber); + if (partNumber != _data->partNumber) + { + THROW (IEX_NAMESPACE::ArgExc, "Unexpected part number " << partNumber + << ", should be " << _data->partNumber << "."); + } + } + + Xdr::read (*_data->_streamData->is, tileXCoord); + Xdr::read (*_data->_streamData->is, tileYCoord); + Xdr::read (*_data->_streamData->is, levelX); + Xdr::read (*_data->_streamData->is, levelY); + + Int64 sampleCountTableSize; + Int64 packedDataSize; + Xdr::read (*_data->_streamData->is, sampleCountTableSize); + + Xdr::read (*_data->_streamData->is, packedDataSize); + + + + if (tileXCoord != dx) + throw IEX_NAMESPACE::InputExc ("Unexpected tile x coordinate."); + + if (tileYCoord != dy) + throw IEX_NAMESPACE::InputExc ("Unexpected tile y coordinate."); + + if (levelX != lx) + throw IEX_NAMESPACE::InputExc ("Unexpected tile x level number coordinate."); + + if (levelY != ly) + throw IEX_NAMESPACE::InputExc ("Unexpected tile y level number coordinate."); + + + // total requirement for reading all the data + + Int64 totalSizeRequired=40+sampleCountTableSize+packedDataSize; + + bool big_enough = totalSizeRequired<=pixelDataSize; + + pixelDataSize = totalSizeRequired; + + // was the block we were given big enough? + if(!big_enough || pixelData==NULL) + { + // special case: seek stream back to start if we are at the beginning (regular reading pixels assumes it doesn't need to seek + // in single part files) + if(!isMultiPart(_data->version)) + { + _data->_streamData->is->seekg(_data->_streamData->currentPosition); + } + // leave lock here - bail before reading more data + return; + } + + // copy the values we have read into the output block + *(int *) (pixelData+0) = dx; + *(int *) (pixelData+4) = dy; + *(int *) (pixelData+8) = levelX; + *(int *) (pixelData+12) = levelY; + *(Int64 *) (pixelData+16) =sampleCountTableSize; + *(Int64 *) (pixelData+24) = packedDataSize; + + // didn't read the unpackedsize - do that now + Xdr::read (*_data->_streamData->is, *(Int64 *) (pixelData+32)); + + // read the actual data + _data->_streamData->is->read(pixelData+40, sampleCountTableSize+packedDataSize); + + + if(!isMultiPart(_data->version)) + { + _data->_streamData->currentPosition+=sampleCountTableSize+packedDataSize+40; + } + + // leave lock here + + +} + + +unsigned int +DeepTiledInputFile::tileXSize () const +{ + return _data->tileDesc.xSize; +} + + +unsigned int +DeepTiledInputFile::tileYSize () const +{ + return _data->tileDesc.ySize; +} + + +LevelMode +DeepTiledInputFile::levelMode () const +{ + return _data->tileDesc.mode; +} + + +LevelRoundingMode +DeepTiledInputFile::levelRoundingMode () const +{ + return _data->tileDesc.roundingMode; +} + + +int +DeepTiledInputFile::numLevels () const +{ + if (levelMode() == RIPMAP_LEVELS) + THROW (IEX_NAMESPACE::LogicExc, "Error calling numLevels() on image " + "file \"" << fileName() << "\" " + "(numLevels() is not defined for files " + "with RIPMAP level mode)."); + + return _data->numXLevels; +} + + +int +DeepTiledInputFile::numXLevels () const +{ + return _data->numXLevels; +} + + +int +DeepTiledInputFile::numYLevels () const +{ + return _data->numYLevels; +} + + +bool +DeepTiledInputFile::isValidLevel (int lx, int ly) const +{ + if (lx < 0 || ly < 0) + return false; + + if (levelMode() == MIPMAP_LEVELS && lx != ly) + return false; + + if (lx >= numXLevels() || ly >= numYLevels()) + return false; + + return true; +} + + +int +DeepTiledInputFile::levelWidth (int lx) const +{ + try + { + return levelSize (_data->minX, _data->maxX, lx, + _data->tileDesc.roundingMode); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error calling levelWidth() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +int +DeepTiledInputFile::levelHeight (int ly) const +{ + try + { + return levelSize (_data->minY, _data->maxY, ly, + _data->tileDesc.roundingMode); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error calling levelHeight() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +int +DeepTiledInputFile::numXTiles (int lx) const +{ + if (lx < 0 || lx >= _data->numXLevels) + { + THROW (IEX_NAMESPACE::ArgExc, "Error calling numXTiles() on image " + "file \"" << _data->_streamData->is->fileName() << "\" " + "(Argument is not in valid range)."); + + } + + return _data->numXTiles[lx]; +} + + +int +DeepTiledInputFile::numYTiles (int ly) const +{ + if (ly < 0 || ly >= _data->numYLevels) + { + THROW (IEX_NAMESPACE::ArgExc, "Error calling numYTiles() on image " + "file \"" << _data->_streamData->is->fileName() << "\" " + "(Argument is not in valid range)."); + } + + return _data->numYTiles[ly]; +} + + +Box2i +DeepTiledInputFile::dataWindowForLevel (int l) const +{ + return dataWindowForLevel (l, l); +} + + +Box2i +DeepTiledInputFile::dataWindowForLevel (int lx, int ly) const +{ + try + { + return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForLevel ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + lx, ly); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error calling dataWindowForLevel() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +Box2i +DeepTiledInputFile::dataWindowForTile (int dx, int dy, int l) const +{ + return dataWindowForTile (dx, dy, l, l); +} + + +Box2i +DeepTiledInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const +{ + try + { + if (!isValidTile (dx, dy, lx, ly)) + throw IEX_NAMESPACE::ArgExc ("Arguments not in valid range."); + + return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + dx, dy, lx, ly); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error calling dataWindowForTile() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +bool +DeepTiledInputFile::isValidTile (int dx, int dy, int lx, int ly) const +{ + return ((lx < _data->numXLevels && lx >= 0) && + (ly < _data->numYLevels && ly >= 0) && + (dx < _data->numXTiles[lx] && dx >= 0) && + (dy < _data->numYTiles[ly] && dy >= 0)); +} + + +void +DeepTiledInputFile::readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int lx, int ly) +{ + Int64 savedFilePos = 0; + + try + { + Lock lock (*_data->_streamData); + + savedFilePos = _data->_streamData->is->tellg(); + + + if (!isValidLevel (lx, ly)) + { + THROW (IEX_NAMESPACE::ArgExc, + "Level coordinate " + "(" << lx << ", " << ly << ") " + "is invalid."); + } + + if (dx1 > dx2) + std::swap (dx1, dx2); + + if (dy1 > dy2) + std::swap (dy1, dy2); + + int dyStart = dy1; + int dyStop = dy2 + 1; + int dY = 1; + + if (_data->lineOrder == DECREASING_Y) + { + dyStart = dy2; + dyStop = dy1 - 1; + dY = -1; + } + + // (TODO) Check if we have read the sample counts for those tiles, + // if we have, no need to read again. + for (int dy = dyStart; dy != dyStop; dy += dY) + { + for (int dx = dx1; dx <= dx2; dx++) + { + + if (!isValidTile (dx, dy, lx, ly)) + { + THROW (IEX_NAMESPACE::ArgExc, + "Tile (" << dx << ", " << dy << ", " << + lx << "," << ly << ") is not a valid tile."); + } + + Box2i tileRange = OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + dx, dy, lx, ly); + + int xOffset = _data->sampleCountXTileCoords * tileRange.min.x; + int yOffset = _data->sampleCountYTileCoords * tileRange.min.y; + + // + // Skip and check the tile coordinates. + // + + _data->_streamData->is->seekg(_data->tileOffsets(dx, dy, lx, ly)); + + if (isMultiPart(_data->version)) + { + int partNumber; + Xdr::read (*_data->_streamData->is, partNumber); + + if (partNumber != _data->partNumber) + throw IEX_NAMESPACE::InputExc ("Unexpected part number."); + } + + int xInFile, yInFile, lxInFile, lyInFile; + Xdr::read (*_data->_streamData->is, xInFile); + Xdr::read (*_data->_streamData->is, yInFile); + Xdr::read (*_data->_streamData->is, lxInFile); + Xdr::read (*_data->_streamData->is, lyInFile); + + if (xInFile != dx) + throw IEX_NAMESPACE::InputExc ("Unexpected tile x coordinate."); + + if (yInFile != dy) + throw IEX_NAMESPACE::InputExc ("Unexpected tile y coordinate."); + + if (lxInFile != lx) + throw IEX_NAMESPACE::InputExc ("Unexpected tile x level number coordinate."); + + if (lyInFile != ly) + throw IEX_NAMESPACE::InputExc ("Unexpected tile y level number coordinate."); + + Int64 tableSize, dataSize, unpackedDataSize; + Xdr::read (*_data->_streamData->is, tableSize); + Xdr::read (*_data->_streamData->is, dataSize); + Xdr::read (*_data->_streamData->is, unpackedDataSize); + + + if(tableSize>_data->maxSampleCountTableSize) + { + THROW (IEX_NAMESPACE::ArgExc, "Bad sampleCountTableDataSize read from tile "<< dx << ',' << dy << ',' << lx << ',' << ly << ": expected " << _data->maxSampleCountTableSize << " or less, got "<< tableSize); + } + + + // + // We make a check on the data size requirements here. + // Whilst we wish to store 64bit sizes on disk, not all the compressors + // have been made to work with such data sizes and are still limited to + // using signed 32 bit (int) for the data size. As such, this version + // insists that we validate that the data size does not exceed the data + // type max limit. + // @TODO refactor the compressor code to ensure full 64-bit support. + // + + Int64 compressorMaxDataSize = Int64(std::numeric_limits::max()); + if (dataSize > compressorMaxDataSize || + unpackedDataSize > compressorMaxDataSize || + tableSize > compressorMaxDataSize) + { + THROW (IEX_NAMESPACE::ArgExc, "This version of the library does not" + << "support the allocation of data with size > " + << compressorMaxDataSize + << " file table size :" << tableSize + << " file unpacked size :" << unpackedDataSize + << " file packed size :" << dataSize << ".\n"); + } + + // + // Read and uncompress the pixel sample count table. + // + + _data->_streamData->is->read(_data->sampleCountTableBuffer, tableSize); + + const char* readPtr; + + if (tableSize < _data->maxSampleCountTableSize) + { + if(!_data->sampleCountTableComp) + { + THROW(IEX_NAMESPACE::ArgExc,"Deep scanline data corrupt at tile " << dx << ',' << dy << ',' << lx << ',' << ly << " (sampleCountTableDataSize error)"); + } + _data->sampleCountTableComp->uncompress(_data->sampleCountTableBuffer, + tableSize, + tileRange.min.y, + readPtr); + } + else + readPtr = _data->sampleCountTableBuffer; + + size_t cumulative_total_samples =0; + int lastAccumulatedCount; + for (int j = tileRange.min.y; j <= tileRange.max.y; j++) + { + lastAccumulatedCount = 0; + for (int i = tileRange.min.x; i <= tileRange.max.x; i++) + { + int accumulatedCount; + Xdr::read (readPtr, accumulatedCount); + + if (accumulatedCount < lastAccumulatedCount) + { + THROW(IEX_NAMESPACE::ArgExc,"Deep tile sampleCount data corrupt at tile " + << dx << ',' << dy << ',' << lx << ',' << ly << " (negative sample count detected)"); + } + + int count = accumulatedCount - lastAccumulatedCount; + lastAccumulatedCount = accumulatedCount; + + _data->getSampleCount(i - xOffset, j - yOffset) =count; + } + cumulative_total_samples += lastAccumulatedCount; + } + + if(cumulative_total_samples * _data->combinedSampleSize > unpackedDataSize) + { + THROW(IEX_NAMESPACE::ArgExc,"Deep scanline sampleCount data corrupt at tile " + << dx << ',' << dy << ',' << lx << ',' << ly + << ": pixel data only contains " << unpackedDataSize + << " bytes of data but table references at least " + << cumulative_total_samples*_data->combinedSampleSize << " bytes of sample data" ); + } + + } + } + + _data->_streamData->is->seekg(savedFilePos); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error reading sample count data from image " + "file \"" << fileName() << "\". " << e.what()); + + _data->_streamData->is->seekg(savedFilePos); + + throw; + } +} + + +void +DeepTiledInputFile::readPixelSampleCount (int dx, int dy, int l) +{ + readPixelSampleCount (dx, dy, l, l); +} + + +void +DeepTiledInputFile::readPixelSampleCount (int dx, int dy, int lx, int ly) +{ + readPixelSampleCounts (dx, dx, dy, dy, lx, ly); +} + + +void +DeepTiledInputFile::readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int l) +{ + readPixelSampleCounts (dx1, dx2, dy1, dy2, l, l); +} + + +size_t +DeepTiledInputFile::totalTiles() const +{ + // + // Calculate the total number of tiles in the file + // + + int numAllTiles = 0; + + switch (levelMode ()) + { + case ONE_LEVEL: + case MIPMAP_LEVELS: + + for (int i_l = 0; i_l < numLevels (); ++i_l) + numAllTiles += numXTiles (i_l) * numYTiles (i_l); + + break; + + case RIPMAP_LEVELS: + + for (int i_ly = 0; i_ly < numYLevels (); ++i_ly) + for (int i_lx = 0; i_lx < numXLevels (); ++i_lx) + numAllTiles += numXTiles (i_lx) * numYTiles (i_ly); + + break; + + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format."); + } + return numAllTiles; +} + + + + +void +DeepTiledInputFile::getTileOrder(int dx[],int dy[],int lx[],int ly[]) const +{ + return _data->tileOffsets.getTileOrder(dx,dy,lx,ly); + +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepTiledInputFile.h b/3rdparty/openexr/IlmImf/ImfDeepTiledInputFile.h new file mode 100644 index 0000000000..2643fe553c --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepTiledInputFile.h @@ -0,0 +1,472 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#ifndef INCLUDED_IMF_DEEP_TILED_INPUT_FILE_H +#define INCLUDED_IMF_DEEP_TILED_INPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class DeepTiledInputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImathBox.h" +#include "ImfTileDescription.h" +#include "ImfThreading.h" +#include "ImfGenericInputFile.h" +#include "ImfDeepFrameBuffer.h" +#include "ImfDeepTiledOutputFile.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class DeepTiledInputFile : public GenericInputFile +{ + public: + + //-------------------------------------------------------------------- + // A constructor that opens the file with the specified name, and + // reads the file header. The constructor throws an IEX_NAMESPACE::ArgExc + // exception if the file is not tiled. + // The numThreads parameter specifies how many worker threads this + // file will try to keep busy when decompressing individual tiles. + // Destroying TiledInputFile objects constructed with this constructor + // automatically closes the corresponding files. + //-------------------------------------------------------------------- + + IMF_EXPORT + DeepTiledInputFile (const char fileName[], + int numThreads = globalThreadCount ()); + + + // ---------------------------------------------------------- + // A constructor that attaches the new TiledInputFile object + // to a file that has already been opened. + // Destroying TiledInputFile objects constructed with this + // constructor does not automatically close the corresponding + // files. + // ---------------------------------------------------------- + + IMF_EXPORT + DeepTiledInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount ()); + + + //----------- + // Destructor + //----------- + + IMF_EXPORT + virtual ~DeepTiledInputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + IMF_EXPORT + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + IMF_EXPORT + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + IMF_EXPORT + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledInputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readTile() is called. + // The current frame buffer can be changed after each call + // to readTile(). + //----------------------------------------------------------- + + IMF_EXPORT + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + IMF_EXPORT + const DeepFrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------ + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window + // (in all levels) are present in the input file, or false if + // any pixels are missing. (Another program may still be busy + // writing the file, or file writing may have been aborted + // prematurely.) + //------------------------------------------------------------ + + IMF_EXPORT + bool isComplete () const; + + + //-------------------------------------------------- + // Utility functions: + //-------------------------------------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + IMF_EXPORT + unsigned int tileXSize () const; + IMF_EXPORT + unsigned int tileYSize () const; + IMF_EXPORT + LevelMode levelMode () const; + IMF_EXPORT + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with + // MIPMAP_LEVELS files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + // totalTiles() returns the total number of tiles in the image + // + //-------------------------------------------------------------------- + + IMF_EXPORT + int numLevels () const; + IMF_EXPORT + int numXLevels () const; + IMF_EXPORT + int numYLevels () const; + IMF_EXPORT + bool isValidLevel (int lx, int ly) const; + IMF_EXPORT + size_t totalTiles() const; + + //---------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //---------------------------------------------------------- + + IMF_EXPORT + int levelWidth (int lx) const; + IMF_EXPORT + int levelHeight (int ly) const; + + + //-------------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //-------------------------------------------------------------- + + IMF_EXPORT + int numXTiles (int lx = 0) const; + IMF_EXPORT + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional region of + // valid pixel coordinates for a level with level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------ + // Read pixel data: + // + // readTile(dx, dy, lx, ly) reads the tile with tile + // coordinates (dx, dy), and level number (lx, ly), + // and stores it in the current frame buffer. + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readTile(dx, dy, level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It calls + // readTile(dx, dy, level, level). + // + // The two readTiles(dx1, dx2, dy1, dy2, ...) functions allow + // reading multiple tiles at once. If multi-threading is used + // the multiple tiles are read concurrently. + // + // Pixels that are outside the pixel coordinate range for the + // tile's level, are never accessed by readTile(). + // + // Attempting to access a tile that is not present in the file + // throws an InputExc exception. + // + //------------------------------------------------------------ + + IMF_EXPORT + void readTile (int dx, int dy, int l = 0); + IMF_EXPORT + void readTile (int dx, int dy, int lx, int ly); + + IMF_EXPORT + void readTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + IMF_EXPORT + void readTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //-------------------------------------------------- + // Read a tile of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement TiledOutputFile::copyPixels()). + //-------------------------------------------------- + + IMF_EXPORT + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + char *pixelData, + Int64 &dataSize) const; + + //------------------------------------------------------------------ + // Read pixel sample counts into a slice in the frame buffer. + // + // readPixelSampleCount(dx, dy, lx, ly) reads the sample counts + // for tile (dx, dy) in level (lx, ly). + // + // readPixelSampleCount(dx, dy, l) calls + // readPixelSampleCount(dx, dy, lx = l, ly = l) + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readPixelSampleCounts(dx1, dx2, dy1, dy2, lx, ly) reads all + // the sample counts for tiles within range + // [(min(dx1, dx2), min(dy1, dy2))...(max(dx1, dx2), max(dy1, dy2)], + // and on level (lx, ly) + // + // readPixelSampleCounts(dx1, dx2, dy1, dy2, l) calls + // readPixelSampleCounts(dx1, dx2, dy1, dy2, lx = l, ly = l). + //------------------------------------------------------------------ + + IMF_EXPORT + void readPixelSampleCount (int dx, int dy, int l = 0); + IMF_EXPORT + void readPixelSampleCount (int dx, int dy, int lx, int ly); + + IMF_EXPORT + void readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int lx, int ly); + + IMF_EXPORT + void readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int l = 0); + + struct Data; + + + + private: + + friend class InputFile; + friend class MultiPartInputFile; + + DeepTiledInputFile (InputPartData* part); + + DeepTiledInputFile (const DeepTiledInputFile &); // not implemented + DeepTiledInputFile & operator = (const DeepTiledInputFile &); // not implemented + + DeepTiledInputFile (const Header &header, OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, int version, + int numThreads); + + void initialize (); + void multiPartInitialize(InputPartData* part); + void compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is); + + bool isValidTile (int dx, int dy, + int lx, int ly) const; + + size_t bytesPerLineForTile (int dx, int dy, + int lx, int ly) const; + + + void getTileOrder(int dx[],int dy[],int lx[],int ly[]) const; + + + Data * _data; + + + // needed for copyPixels + friend void DeepTiledOutputFile::copyPixels(DeepTiledInputFile &); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfDeepTiledInputPart.cpp b/3rdparty/openexr/IlmImf/ImfDeepTiledInputPart.cpp new file mode 100644 index 0000000000..0f0c012a06 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepTiledInputPart.cpp @@ -0,0 +1,273 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#include "ImfDeepTiledInputPart.h" +#include "ImfMultiPartInputFile.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +DeepTiledInputPart::DeepTiledInputPart(MultiPartInputFile& multiPartFile, int partNumber) +{ + file = multiPartFile.getInputPart(partNumber); +} + + +const char * +DeepTiledInputPart::fileName () const +{ + return file->fileName(); +} + + +const Header & +DeepTiledInputPart::header () const +{ + return file->header(); +} + + +int +DeepTiledInputPart::version () const +{ + return file->version(); +} + + +void +DeepTiledInputPart::setFrameBuffer (const DeepFrameBuffer &frameBuffer) +{ + file->setFrameBuffer(frameBuffer); +} + + +const DeepFrameBuffer & +DeepTiledInputPart::frameBuffer () const +{ + return file->frameBuffer(); +} + + +bool +DeepTiledInputPart::isComplete () const +{ + return file->isComplete(); +} + + +unsigned int +DeepTiledInputPart::tileXSize () const +{ + return file->tileXSize(); +} + + +unsigned int +DeepTiledInputPart::tileYSize () const +{ + return file->tileYSize(); +} + + +LevelMode +DeepTiledInputPart::levelMode () const +{ + return file->levelMode(); +} + + +LevelRoundingMode +DeepTiledInputPart::levelRoundingMode () const +{ + return file->levelRoundingMode(); +} + + +int +DeepTiledInputPart::numLevels () const +{ + return file->numLevels(); +} + + +int +DeepTiledInputPart::numXLevels () const +{ + return file->numXLevels(); +} + + +int +DeepTiledInputPart::numYLevels () const +{ + return file->numYLevels(); +} + + +bool +DeepTiledInputPart::isValidLevel (int lx, int ly) const +{ + return file->isValidLevel(lx, ly); +} + + +int +DeepTiledInputPart::levelWidth (int lx) const +{ + return file->levelWidth(lx); +} + + +int +DeepTiledInputPart::levelHeight (int ly) const +{ + return file->levelHeight(ly); +} + + +int +DeepTiledInputPart::numXTiles (int lx) const +{ + return file->numXTiles(lx); +} + + +int +DeepTiledInputPart::numYTiles (int ly) const +{ + return file->numYTiles(ly); +} + + +IMATH_NAMESPACE::Box2i +DeepTiledInputPart::dataWindowForLevel (int l) const +{ + return file->dataWindowForLevel(l); +} + +IMATH_NAMESPACE::Box2i +DeepTiledInputPart::dataWindowForLevel (int lx, int ly) const +{ + return file->dataWindowForLevel(lx, ly); +} + + +IMATH_NAMESPACE::Box2i +DeepTiledInputPart::dataWindowForTile (int dx, int dy, int l) const +{ + return file->dataWindowForTile(dx, dy, l); +} + + +IMATH_NAMESPACE::Box2i +DeepTiledInputPart::dataWindowForTile (int dx, int dy, + int lx, int ly) const +{ + return file->dataWindowForTile(dx, dy, lx, ly); +} + + +void +DeepTiledInputPart::readTile (int dx, int dy, int l) +{ + file->readTile(dx, dy, l); +} + + +void +DeepTiledInputPart::readTile (int dx, int dy, int lx, int ly) +{ + file->readTile(dx, dy, lx, ly); +} + + +void +DeepTiledInputPart::readTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly) +{ + file->readTiles(dx1, dx2, dy1, dy2, lx, ly); +} + + +void +DeepTiledInputPart::readTiles (int dx1, int dx2, int dy1, int dy2, + int l) +{ + file->readTiles(dx1, dx2, dy1, dy2, l); +} + + +void +DeepTiledInputPart::rawTileData (int &dx, int &dy, + int &lx, int &ly, + char * pixelData, + Int64 & dataSize) const +{ + file->rawTileData(dx, dy, lx, ly, pixelData, dataSize ); +} + + +void +DeepTiledInputPart::readPixelSampleCount (int dx, int dy, int l) +{ + file->readPixelSampleCount(dx, dy, l); +} + + +void +DeepTiledInputPart::readPixelSampleCount (int dx, int dy, int lx, int ly) +{ + file->readPixelSampleCount(dx, dy, lx, ly); +} + + +void +DeepTiledInputPart::readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int lx, int ly) +{ + file->readPixelSampleCounts(dx1, dx2, dy1, dy2, lx, ly); +} + +void +DeepTiledInputPart::readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int l) +{ + file->readPixelSampleCounts(dx1, dx2, dy1, dy2, l); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepTiledInputPart.h b/3rdparty/openexr/IlmImf/ImfDeepTiledInputPart.h new file mode 100644 index 0000000000..0e665c2316 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepTiledInputPart.h @@ -0,0 +1,394 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#ifndef IMFDEEPTILEDINPUTPART_H_ +#define IMFDEEPTILEDINPUTPART_H_ + +#include "ImfDeepTiledInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class DeepTiledInputPart +{ + public: + + IMF_EXPORT + DeepTiledInputPart(MultiPartInputFile& multiPartFile, int partNumber); + + //------------------------ + // Access to the file name + //------------------------ + + IMF_EXPORT + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + IMF_EXPORT + const Header & header () const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + IMF_EXPORT + int version () const; + + + //----------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledInputFile object. + // + // The current frame buffer is the destination for the pixel + // data read from the file. The current frame buffer must be + // set at least once before readTile() is called. + // The current frame buffer can be changed after each call + // to readTile(). + //----------------------------------------------------------- + + IMF_EXPORT + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + IMF_EXPORT + const DeepFrameBuffer & frameBuffer () const; + + + //------------------------------------------------------------ + // Check if the file is complete: + // + // isComplete() returns true if all pixels in the data window + // (in all levels) are present in the input file, or false if + // any pixels are missing. (Another program may still be busy + // writing the file, or file writing may have been aborted + // prematurely.) + //------------------------------------------------------------ + + IMF_EXPORT + bool isComplete () const; + + + //-------------------------------------------------- + // Utility functions: + //-------------------------------------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + IMF_EXPORT + unsigned int tileXSize () const; + IMF_EXPORT + unsigned int tileYSize () const; + IMF_EXPORT + LevelMode levelMode () const; + IMF_EXPORT + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with + // MIPMAP_LEVELS files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + //-------------------------------------------------------------------- + + IMF_EXPORT + int numLevels () const; + IMF_EXPORT + int numXLevels () const; + IMF_EXPORT + int numYLevels () const; + IMF_EXPORT + bool isValidLevel (int lx, int ly) const; + + + //---------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //---------------------------------------------------------- + + IMF_EXPORT + int levelWidth (int lx) const; + IMF_EXPORT + int levelHeight (int ly) const; + + + //-------------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //-------------------------------------------------------------- + + IMF_EXPORT + int numXTiles (int lx = 0) const; + IMF_EXPORT + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional region of + // valid pixel coordinates for a level with level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------ + // Read pixel data: + // + // readTile(dx, dy, lx, ly) reads the tile with tile + // coordinates (dx, dy), and level number (lx, ly), + // and stores it in the current frame buffer. + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readTile(dx, dy, level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It calls + // readTile(dx, dy, level, level). + // + // The two readTiles(dx1, dx2, dy1, dy2, ...) functions allow + // reading multiple tiles at once. If multi-threading is used + // the multiple tiles are read concurrently. + // + // Pixels that are outside the pixel coordinate range for the + // tile's level, are never accessed by readTile(). + // + // Attempting to access a tile that is not present in the file + // throws an InputExc exception. + // + //------------------------------------------------------------ + + IMF_EXPORT + void readTile (int dx, int dy, int l = 0); + IMF_EXPORT + void readTile (int dx, int dy, int lx, int ly); + + IMF_EXPORT + void readTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + IMF_EXPORT + void readTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //-------------------------------------------------- + // Read a tile of raw pixel data from the file, + // without uncompressing it (this function is + // used to implement TiledOutputFile::copyPixels()). + //-------------------------------------------------- + + IMF_EXPORT + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + char *data, + Int64 &dataSize + ) const; + + //------------------------------------------------------------------ + // Read pixel sample counts into a slice in the frame buffer. + // + // readPixelSampleCount(dx, dy, lx, ly) reads the sample counts + // for tile (dx, dy) in level (lx, ly). + // + // readPixelSampleCount(dx, dy, l) calls + // readPixelSampleCount(dx, dy, lx = l, ly = l) + // + // dx must lie in the interval [0, numXTiles(lx)-1] + // dy must lie in the interval [0, numYTiles(ly)-1] + // + // lx must lie in the interval [0, numXLevels()-1] + // ly must lie in the inverval [0, numYLevels()-1] + // + // readPixelSampleCounts(dx1, dx2, dy1, dy2, lx, ly) reads all + // the sample counts for tiles within range + // [(min(dx1, dx2), min(dy1, dy2))...(max(dx1, dx2), max(dy1, dy2)], + // and on level (lx, ly) + // + // readPixelSampleCounts(dx1, dx2, dy1, dy2, l) calls + // readPixelSampleCounts(dx1, dx2, dy1, dy2, lx = l, ly = l). + //------------------------------------------------------------------ + + IMF_EXPORT + void readPixelSampleCount (int dx, int dy, int l = 0); + IMF_EXPORT + void readPixelSampleCount (int dx, int dy, int lx, int ly); + + IMF_EXPORT + void readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int lx, int ly); + + IMF_EXPORT + void readPixelSampleCounts (int dx1, int dx2, + int dy1, int dy2, + int l = 0); + + private: + DeepTiledInputFile* file; + + friend void DeepTiledOutputFile::copyPixels(DeepTiledInputPart &); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif /* IMFDEEPTILEDINPUTPART_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfDeepTiledOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfDeepTiledOutputFile.cpp new file mode 100644 index 0000000000..ef79135a42 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepTiledOutputFile.cpp @@ -0,0 +1,2055 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +//----------------------------------------------------------------------------- +// +// class DeepTiledOutputFile +// +//----------------------------------------------------------------------------- + +#include "ImfDeepTiledOutputFile.h" +#include "ImfDeepTiledInputFile.h" +#include "ImfDeepTiledInputPart.h" +#include "ImfInputFile.h" +#include "ImfTileDescriptionAttribute.h" +#include "ImfPreviewImageAttribute.h" +#include "ImfChannelList.h" +#include "ImfMisc.h" +#include "ImfTiledMisc.h" +#include "ImfStdIO.h" +#include "ImfCompressor.h" +#include "ImfOutputStreamMutex.h" +#include "ImfOutputPartData.h" +#include "ImfArray.h" +#include "ImfXdr.h" +#include "ImfVersion.h" +#include "ImfTileOffsets.h" +#include "ImfThreading.h" +#include "ImfPartType.h" + +#include "ImathBox.h" + +#include "IlmThreadPool.h" +#include "IlmThreadSemaphore.h" +#include "IlmThreadMutex.h" + +#include "Iex.h" + +#include +#include +#include +#include +#include +#include + +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::V2i; +using std::string; +using std::vector; +using std::ofstream; +using std::map; +using std::min; +using std::max; +using std::swap; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using ILMTHREAD_NAMESPACE::Semaphore; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; + +namespace { + +struct TOutSliceInfo +{ + PixelType type; + const char * base; + size_t sampleStride; + size_t xStride; + size_t yStride; + bool zero; + int xTileCoords; + int yTileCoords; + + TOutSliceInfo (PixelType type = HALF, + size_t sampleStride = 0, + size_t xStride = 0, + size_t yStride = 0, + bool zero = false, + int xTileCoords = 0, + int yTileCoords = 0); +}; + + +TOutSliceInfo::TOutSliceInfo (PixelType t, + size_t spst, + size_t xStride, + size_t yStride, + bool z, + int xtc, + int ytc) +: + type (t), + sampleStride (spst), + xStride(xStride), + yStride(yStride), + zero (z), + xTileCoords (xtc), + yTileCoords (ytc) +{ + // empty +} + + +struct TileCoord +{ + int dx; + int dy; + int lx; + int ly; + + + TileCoord (int xTile = 0, int yTile = 0, + int xLevel = 0, int yLevel = 0) + : + dx (xTile), dy (yTile), + lx (xLevel), ly (yLevel) + { + // empty + } + + + bool + operator < (const TileCoord &other) const + { + return (ly < other.ly) || + (ly == other.ly && lx < other.lx) || + ((ly == other.ly && lx == other.lx) && + ((dy < other.dy) || (dy == other.dy && dx < other.dx))); + } + + + bool + operator == (const TileCoord &other) const + { + return lx == other.lx && + ly == other.ly && + dx == other.dx && + dy == other.dy; + } +}; + + +struct BufferedTile +{ + char * pixelData; + Int64 pixelDataSize; + Int64 unpackedDataSize; + char * sampleCountTableData; + Int64 sampleCountTableSize; + + BufferedTile (const char *data, int size, int unpackedSize, + const char *tableData, int tableSize): + pixelData (0), + pixelDataSize(size), + unpackedDataSize(unpackedSize), + sampleCountTableData(0), + sampleCountTableSize(tableSize) + { + pixelData = new char[pixelDataSize]; + memcpy (pixelData, data, pixelDataSize); + + sampleCountTableData = new char[tableSize]; + memcpy (sampleCountTableData, tableData, tableSize); + } + + ~BufferedTile() + { + delete [] pixelData; + delete [] sampleCountTableData; + } +}; + + +typedef map TileMap; + + +struct TileBuffer +{ + Array buffer; + const char * dataPtr; + Int64 dataSize; + Int64 uncompressedSize; + Compressor * compressor; + Array sampleCountTableBuffer; + const char * sampleCountTablePtr; + Int64 sampleCountTableSize; + Compressor* sampleCountTableCompressor; + TileCoord tileCoord; + bool hasException; + string exception; + + TileBuffer (); + ~TileBuffer (); + + inline void wait () {_sem.wait();} + inline void post () {_sem.post();} + + protected: + + Semaphore _sem; +}; + + +TileBuffer::TileBuffer (): + dataPtr (0), + dataSize (0), + compressor (0), + sampleCountTablePtr (0), + sampleCountTableCompressor (0), + hasException (false), + exception (), + _sem (1) +{ + // empty +} + + +TileBuffer::~TileBuffer () +{ + if (compressor != 0) + delete compressor; + + if (sampleCountTableCompressor != 0) + delete sampleCountTableCompressor; +} + + +} // namespace + + +struct DeepTiledOutputFile::Data +{ + Header header; // the image header + int version; // file format version + bool multipart; // file is multipart + TileDescription tileDesc; // describes the tile layout + DeepFrameBuffer frameBuffer; // framebuffer to write into + Int64 previewPosition; + LineOrder lineOrder; // the file's lineorder + int minX; // data window's min x coord + int maxX; // data window's max x coord + int minY; // data window's min y coord + int maxY; // data window's max x coord + + int numXLevels; // number of x levels + int numYLevels; // number of y levels + int * numXTiles; // number of x tiles at a level + int * numYTiles; // number of y tiles at a level + + TileOffsets tileOffsets; // stores offsets in file for + // each tile + + Compressor::Format format; // compressor's data format + vector slices; // info about channels in file + + vector tileBuffers; + + Int64 tileOffsetsPosition; // position of the tile index + + TileMap tileMap; // the map of buffered tiles + TileCoord nextTileToWrite; + + int partNumber; // the output part number + + char* sampleCountSliceBase; // the pointer to the number + // of samples in each pixel + int sampleCountXStride; // the x stride for sampleCountSliceBase + int sampleCountYStride; // the y stride for sampleCountSliceBase + int sampleCountXTileCoords; // using x coordinates relative to current tile + int sampleCountYTileCoords; // using y coordinates relative to current tile + + Int64 maxSampleCountTableSize;// the max size in bytes for a pixel + // sample count table + OutputStreamMutex* _streamData; + bool _deleteStream; + + Data (int numThreads); + ~Data (); + + inline TileBuffer * getTileBuffer (int number); + // hash function from tile + // buffer coords into our + // vector of tile buffers + + int& getSampleCount(int x, int y); + // get the number of samples + // in each pixel + + TileCoord nextTileCoord (const TileCoord &a); +}; + + +DeepTiledOutputFile::Data::Data (int numThreads): + numXTiles(0), + numYTiles(0), + tileOffsetsPosition (0), + partNumber(-1), + _streamData(NULL), + _deleteStream(true) +{ + // + // We need at least one tileBuffer, but if threading is used, + // to keep n threads busy we need 2*n tileBuffers + // + + tileBuffers.resize (max (1, 2 * numThreads)); + for (size_t i = 0; i < tileBuffers.size(); i++) + tileBuffers[i] = 0; +} + + +DeepTiledOutputFile::Data::~Data () +{ + delete [] numXTiles; + delete [] numYTiles; + + // + // Delete all the tile buffers, if any still happen to exist + // + + for (TileMap::iterator i = tileMap.begin(); i != tileMap.end(); ++i) + delete i->second; + + for (size_t i = 0; i < tileBuffers.size(); i++) + if (tileBuffers[i] != 0) + delete tileBuffers[i]; + + for (size_t i = 0; i < slices.size(); i++) + delete slices[i]; +} + + +int& +DeepTiledOutputFile::Data::getSampleCount(int x, int y) +{ + return sampleCount(sampleCountSliceBase, + sampleCountXStride, + sampleCountYStride, + x, y); +} + + +TileBuffer* +DeepTiledOutputFile::Data::getTileBuffer (int number) +{ + return tileBuffers[number % tileBuffers.size()]; +} + + +TileCoord +DeepTiledOutputFile::Data::nextTileCoord (const TileCoord &a) +{ + TileCoord b = a; + + if (lineOrder == INCREASING_Y) + { + b.dx++; + + if (b.dx >= numXTiles[b.lx]) + { + b.dx = 0; + b.dy++; + + if (b.dy >= numYTiles[b.ly]) + { + // + // the next tile is in the next level + // + + b.dy = 0; + + switch (tileDesc.mode) + { + case ONE_LEVEL: + case MIPMAP_LEVELS: + + b.lx++; + b.ly++; + break; + + case RIPMAP_LEVELS: + + b.lx++; + + if (b.lx >= numXLevels) + { + b.lx = 0; + b.ly++; + + #ifdef DEBUG + assert (b.ly <= numYLevels); + #endif + } + break; + case NUM_LEVELMODES : + throw IEX_NAMESPACE::LogicExc("unknown level mode computing nextTileCoord"); + } + } + } + } + else if (lineOrder == DECREASING_Y) + { + b.dx++; + + if (b.dx >= numXTiles[b.lx]) + { + b.dx = 0; + b.dy--; + + if (b.dy < 0) + { + // + // the next tile is in the next level + // + + switch (tileDesc.mode) + { + case ONE_LEVEL: + case MIPMAP_LEVELS: + + b.lx++; + b.ly++; + break; + + case RIPMAP_LEVELS: + + b.lx++; + + if (b.lx >= numXLevels) + { + b.lx = 0; + b.ly++; + + #ifdef DEBUG + assert (b.ly <= numYLevels); + #endif + } + break; + case NUM_LEVELMODES : + throw IEX_NAMESPACE::LogicExc("unknown level mode computing nextTileCoord"); + } + + if (b.ly < numYLevels) + b.dy = numYTiles[b.ly] - 1; + } + } + }else if(lineOrder==RANDOM_Y) + { + THROW (IEX_NAMESPACE::ArgExc, + "can't compute next tile from randomly ordered image: use getTilesInOrder instead"); + + } + + return b; +} + + +namespace { + +void +writeTileData (DeepTiledOutputFile::Data *ofd, + int dx, int dy, + int lx, int ly, + const char pixelData[], + Int64 pixelDataSize, + Int64 unpackedDataSize, + const char sampleCountTableData[], + Int64 sampleCountTableSize) +{ + + // + // Store a block of pixel data in the output file, and try + // to keep track of the current writing position the file, + // without calling tellp() (tellp() can be fairly expensive). + // + + Int64 currentPosition = ofd->_streamData->currentPosition; + ofd->_streamData->currentPosition = 0; + + if (currentPosition == 0) + currentPosition = ofd->_streamData->os->tellp(); + + ofd->tileOffsets (dx, dy, lx, ly) = currentPosition; + + #ifdef DEBUG + assert (ofd->_streamData->os->tellp() == currentPosition); + #endif + + // + // Write the tile header. + // + + if (ofd->multipart) + { + Xdr::write (*ofd->_streamData->os, ofd->partNumber); + } + Xdr::write (*ofd->_streamData->os, dx); + Xdr::write (*ofd->_streamData->os, dy); + Xdr::write (*ofd->_streamData->os, lx); + Xdr::write (*ofd->_streamData->os, ly); + + // + // Write the packed size of the pixel sample count table (64 bits) + // + + Xdr::write (*ofd->_streamData->os, sampleCountTableSize); + + // + // Write the packed and unpacked data size (64 bits each) + // + + Xdr::write (*ofd->_streamData->os, pixelDataSize); + Xdr::write (*ofd->_streamData->os, unpackedDataSize); + + // + // Write the compressed pixel sample count table. + // + + ofd->_streamData->os->write (sampleCountTableData, sampleCountTableSize); + + // + // Write the compressed data. + // + + ofd->_streamData->os->write (pixelData, pixelDataSize); + + // + // Keep current position in the file so that we can avoid + // redundant seekg() operations (seekg() can be fairly expensive). + // + + ofd->_streamData->currentPosition = currentPosition + + 4 * Xdr::size() + // dx, dy, lx, ly, + 3 * Xdr::size() + // sampleCountTableSize, + // pixelDataSize, + // unpackedDataSize + sampleCountTableSize + + pixelDataSize; + + if (ofd->multipart) + { + ofd->_streamData->currentPosition += Xdr::size(); + } +} + + + +void +bufferedTileWrite ( + DeepTiledOutputFile::Data *ofd, + int dx, int dy, + int lx, int ly, + const char pixelData[], + Int64 pixelDataSize, + Int64 unpackedDataSize, + const char sampleCountTableData[], + Int64 sampleCountTableSize) +{ + // + // Check if a tile with coordinates (dx,dy,lx,ly) has already been written. + // + + if (ofd->tileOffsets (dx, dy, lx, ly)) + { + THROW (IEX_NAMESPACE::ArgExc, + "Attempt to write tile " + "(" << dx << ", " << dy << ", " << lx << ", " << ly << ") " + "more than once."); + } + + // + // If tiles can be written in random order, then don't buffer anything. + // + + if (ofd->lineOrder == RANDOM_Y) + { + writeTileData (ofd, dx, dy, lx, ly, + pixelData, pixelDataSize, unpackedDataSize, + sampleCountTableData, sampleCountTableSize); + return; + } + + // + // If the tiles cannot be written in random order, then check if a + // tile with coordinates (dx,dy,lx,ly) has already been buffered. + // + + TileCoord currentTile = TileCoord(dx, dy, lx, ly); + + if (ofd->tileMap.find (currentTile) != ofd->tileMap.end()) + { + THROW (IEX_NAMESPACE::ArgExc, + "Attempt to write tile " + "(" << dx << ", " << dy << ", " << lx << ", " << ly << ") " + "more than once."); + } + + // + // If all the tiles before this one have already been written to the file, + // then write this tile immediately and check if we have buffered tiles + // that can be written after this tile. + // + // Otherwise, buffer the tile so it can be written to file later. + // + + if (ofd->nextTileToWrite == currentTile) + { + writeTileData (ofd, dx, dy, lx, ly, + pixelData, pixelDataSize, unpackedDataSize, + sampleCountTableData, sampleCountTableSize); + ofd->nextTileToWrite = ofd->nextTileCoord (ofd->nextTileToWrite); + + TileMap::iterator i = ofd->tileMap.find (ofd->nextTileToWrite); + + // + // Step through the tiles and write all successive buffered tiles after + // the current one. + // + + while(i != ofd->tileMap.end()) + { + // + // Write the tile, and then delete the tile's buffered data + // + + writeTileData (ofd, + i->first.dx, i->first.dy, + i->first.lx, i->first.ly, + i->second->pixelData, + i->second->pixelDataSize, + i->second->unpackedDataSize, + i->second->sampleCountTableData, + i->second->sampleCountTableSize); + + delete i->second; + ofd->tileMap.erase (i); + + // + // Proceed to the next tile + // + + ofd->nextTileToWrite = ofd->nextTileCoord (ofd->nextTileToWrite); + i = ofd->tileMap.find (ofd->nextTileToWrite); + } + } + else + { + // + // Create a new BufferedTile, copy the pixelData into it, and + // insert it into the tileMap. + // + + ofd->tileMap[currentTile] = + new BufferedTile ((const char *)pixelData, pixelDataSize, unpackedDataSize, + sampleCountTableData, sampleCountTableSize); + } +} + + +void +convertToXdr (DeepTiledOutputFile::Data *ofd, + Array& tileBuffer, + int numScanLines, + vector& bytesPerLine) +{ + // + // Convert the contents of a TiledOutputFile's tileBuffer from the + // machine's native representation to Xdr format. This function is called + // by writeTile(), below, if the compressor wanted its input pixel data + // in the machine's native format, but then failed to compress the data + // (most compressors will expand rather than compress random input data). + // + // Note that this routine assumes that the machine's native representation + // of the pixel data has the same size as the Xdr representation. This + // makes it possible to convert the pixel data in place, without an + // intermediate temporary buffer. + // + + // + // Set these to point to the start of the tile. + // We will write to toPtr, and read from fromPtr. + // + + char *writePtr = tileBuffer; + const char *readPtr = writePtr; + + // + // Iterate over all scan lines in the tile. + // + + for (int y = 0; y < numScanLines; ++y) + { + // + // Iterate over all slices in the file. + // + + for (unsigned int i = 0; i < ofd->slices.size(); ++i) + { + const TOutSliceInfo &slice = *ofd->slices[i]; + + // + // Convert the samples in place. + // + + Int64 numPixelsPerScanLine = bytesPerLine[y]; + + convertInPlace (writePtr, readPtr, slice.type, + numPixelsPerScanLine); + } + } + + #ifdef DEBUG + + assert (writePtr == readPtr); + + #endif +} + + +// +// A TileBufferTask encapsulates the task of copying a tile from +// the user's framebuffer into a LineBuffer and compressing the data +// if necessary. +// + +class TileBufferTask: public Task +{ + public: + + TileBufferTask (TaskGroup *group, + DeepTiledOutputFile::Data *ofd, + int number, + int dx, int dy, + int lx, int ly); + + virtual ~TileBufferTask (); + + virtual void execute (); + + private: + + DeepTiledOutputFile::Data * _ofd; + TileBuffer * _tileBuffer; +}; + + +TileBufferTask::TileBufferTask + (TaskGroup *group, + DeepTiledOutputFile::Data *ofd, + int number, + int dx, int dy, + int lx, int ly) +: + Task (group), + _ofd (ofd), + _tileBuffer (_ofd->getTileBuffer (number)) +{ + // + // Wait for the tileBuffer to become available + // + + _tileBuffer->wait (); + _tileBuffer->tileCoord = TileCoord (dx, dy, lx, ly); +} + + +TileBufferTask::~TileBufferTask () +{ + // + // Signal that the tile buffer is now free + // + + _tileBuffer->post (); +} + + +void +TileBufferTask::execute () +{ + try + { + // + // First copy the pixel data from the frame buffer + // into the tile buffer + // + // Convert one tile's worth of pixel data to + // a machine-independent representation, and store + // the result in _tileBuffer->buffer. + // + + Box2i tileRange = OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile ( + _ofd->tileDesc, + _ofd->minX, _ofd->maxX, + _ofd->minY, _ofd->maxY, + _tileBuffer->tileCoord.dx, + _tileBuffer->tileCoord.dy, + _tileBuffer->tileCoord.lx, + _tileBuffer->tileCoord.ly); + + int numScanLines = tileRange.max.y - tileRange.min.y + 1; +// int numPixelsPerScanLine = tileRange.max.x - tileRange.min.x + 1; + + // + // Get the bytes for each line. + // + + vector bytesPerLine(_ofd->tileDesc.ySize); + vector xOffsets(_ofd->slices.size()); + vector yOffsets(_ofd->slices.size()); + for (size_t i = 0; i < _ofd->slices.size(); i++) + { + const TOutSliceInfo &slice = *_ofd->slices[i]; + xOffsets[i] = slice.xTileCoords * tileRange.min.x; + yOffsets[i] = slice.yTileCoords * tileRange.min.y; + } + + calculateBytesPerLine(_ofd->header, + _ofd->sampleCountSliceBase, + _ofd->sampleCountXStride, + _ofd->sampleCountYStride, + tileRange.min.x, tileRange.max.x, + tileRange.min.y, tileRange.max.y, + xOffsets, yOffsets, + bytesPerLine); + + // + // Allocate the memory for internal buffer. + // (TODO) more efficient memory management? + // + + Int64 totalBytes = 0; + Int64 maxBytesPerTileLine = 0; + for (size_t i = 0; i < bytesPerLine.size(); i++) + { + totalBytes += bytesPerLine[i]; + if (bytesPerLine[i] > maxBytesPerTileLine) + maxBytesPerTileLine = bytesPerLine[i]; + } + _tileBuffer->buffer.resizeErase(totalBytes); + + char *writePtr = _tileBuffer->buffer; + + // + // Iterate over the scan lines in the tile. + // + + int xOffsetForSampleCount = + (_ofd->sampleCountXTileCoords == 0) ? 0 : tileRange.min.x; + int yOffsetForSampleCount = + (_ofd->sampleCountYTileCoords == 0) ? 0 : tileRange.min.y; + + for (int y = tileRange.min.y; y <= tileRange.max.y; ++y) + { + // + // Iterate over all image channels. + // + + for (unsigned int i = 0; i < _ofd->slices.size(); ++i) + { + const TOutSliceInfo &slice = *_ofd->slices[i]; + + + // + // Fill the tile buffer with pixel data. + // + + if (slice.zero) + { + // + // The frame buffer contains no data for this channel. + // Store zeroes in _data->tileBuffer. + // + + fillChannelWithZeroes (writePtr, _ofd->format, slice.type, + bytesPerLine[y - tileRange.min.y]); + } + else + { + // + // The frame buffer contains data for this channel. + // + + + int xOffsetForData = slice.xTileCoords ? tileRange.min.x : 0; + int yOffsetForData = slice.yTileCoords ? tileRange.min.y : 0; + + // (TOOD) treat sample count offsets differently. + copyFromDeepFrameBuffer (writePtr, + slice.base, + _ofd->sampleCountSliceBase, + _ofd->sampleCountXStride, + _ofd->sampleCountYStride, + y, + tileRange.min.x, + tileRange.max.x, + xOffsetForSampleCount, + yOffsetForSampleCount, + xOffsetForData, + yOffsetForData, + slice.sampleStride, + slice.xStride, + slice.yStride, + _ofd->format, + slice.type); +#if defined(DEBUG) + assert(writePtr-_tileBuffer->buffer<=totalBytes); +#endif + } + } + } + + // + // Compress the pixel sample count table. + // + + char* ptr = _tileBuffer->sampleCountTableBuffer; + Int64 tableDataSize = 0; + for (int i = tileRange.min.y; i <= tileRange.max.y; i++) + { + int count = 0; + for (int j = tileRange.min.x; j <= tileRange.max.x; j++) + { + count += _ofd->getSampleCount(j - xOffsetForSampleCount, + i - yOffsetForSampleCount); + Xdr::write (ptr, count); + tableDataSize += sizeof (int); + } + } + + if(_tileBuffer->sampleCountTableCompressor) + { + _tileBuffer->sampleCountTableSize = + _tileBuffer->sampleCountTableCompressor->compress ( + _tileBuffer->sampleCountTableBuffer, + tableDataSize, + tileRange.min.y, + _tileBuffer->sampleCountTablePtr); + } + + // + // If we can't make data shrink (or compression was disabled), then just use the raw data. + // + + if ( ! _tileBuffer->sampleCountTableCompressor || + _tileBuffer->sampleCountTableSize >= _ofd->maxSampleCountTableSize) + { + _tileBuffer->sampleCountTableSize = _ofd->maxSampleCountTableSize; + _tileBuffer->sampleCountTablePtr = _tileBuffer->sampleCountTableBuffer; + } + + // + // Compress the contents of the tileBuffer, + // and store the compressed data in the output file. + // + + _tileBuffer->dataSize = writePtr - _tileBuffer->buffer; + _tileBuffer->uncompressedSize = _tileBuffer->dataSize; + _tileBuffer->dataPtr = _tileBuffer->buffer; + + // (TODO) don't do this all the time. + if (_tileBuffer->compressor != 0) + delete _tileBuffer->compressor; + _tileBuffer->compressor = newTileCompressor + (_ofd->header.compression(), + maxBytesPerTileLine, + _ofd->tileDesc.ySize, + _ofd->header); + + if (_tileBuffer->compressor) + { + const char *compPtr; + + Int64 compSize = _tileBuffer->compressor->compressTile + (_tileBuffer->dataPtr, + _tileBuffer->dataSize, + tileRange, compPtr); + + if (compSize < _tileBuffer->dataSize) + { + _tileBuffer->dataSize = compSize; + _tileBuffer->dataPtr = compPtr; + } + else if (_ofd->format == Compressor::NATIVE) + { + // + // The data did not shrink during compression, but + // we cannot write to the file using native format, + // so we need to convert the lineBuffer to Xdr. + // + + convertToXdr (_ofd, _tileBuffer->buffer, numScanLines, + bytesPerLine); + } + } + } + catch (std::exception &e) + { + if (!_tileBuffer->hasException) + { + _tileBuffer->exception = e.what (); + _tileBuffer->hasException = true; + } + } + catch (...) + { + if (!_tileBuffer->hasException) + { + _tileBuffer->exception = "unrecognized exception"; + _tileBuffer->hasException = true; + } + } +} + +} // namespace + + +DeepTiledOutputFile::DeepTiledOutputFile + (const char fileName[], + const Header &header, + int numThreads) +: + _data (new Data (numThreads)) + +{ + _data->_streamData=new OutputStreamMutex(); + _data->_deleteStream =true; + try + { + header.sanityCheck (true); + _data->_streamData->os = new StdOFStream (fileName); + initialize (header); + _data->_streamData->currentPosition = _data->_streamData->os->tellp(); + + // Write header and empty offset table to the file. + writeMagicNumberAndVersionField(*_data->_streamData->os, _data->header); + _data->previewPosition = _data->header.writeTo (*_data->_streamData->os, true); + _data->tileOffsetsPosition = _data->tileOffsets.writeTo (*_data->_streamData->os); + _data->multipart = false; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + if (_data && _data->_streamData && _data->_streamData->os) delete _data->_streamData->os; + if (_data && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + REPLACE_EXC (e, "Cannot open image file " + "\"" << fileName << "\". " << e.what()); + throw; + } + catch (...) + { + if (_data && _data->_streamData && _data->_streamData->os) delete _data->_streamData->os; + if (_data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + throw; + } +} + + +DeepTiledOutputFile::DeepTiledOutputFile + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + int numThreads) +: + _data (new Data (numThreads)) +{ + _data->_streamData=new OutputStreamMutex(); + _data->_deleteStream=false; + + try + { + header.sanityCheck(true); + _data->_streamData->os = &os; + initialize (header); + _data->_streamData->currentPosition = _data->_streamData->os->tellp(); + + // Write header and empty offset table to the file. + writeMagicNumberAndVersionField(*_data->_streamData->os, _data->header); + _data->previewPosition = _data->header.writeTo (*_data->_streamData->os, true); + _data->tileOffsetsPosition = _data->tileOffsets.writeTo (*_data->_streamData->os); + _data->multipart = false; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + if (_data && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + REPLACE_EXC (e, "Cannot open image file " + "\"" << os.fileName() << "\". " << e.what()); + throw; + } + catch (...) + { + if (_data && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + + throw; + } +} + +DeepTiledOutputFile::DeepTiledOutputFile(const OutputPartData* part) +{ + + try + { + if (part->header.type() != DEEPTILE) + throw IEX_NAMESPACE::ArgExc("Can't build a DeepTiledOutputFile from " + "a type-mismatched part."); + + _data = new Data (part->numThreads); + _data->_streamData=part->mutex; + _data->_deleteStream=false; + initialize(part->header); + _data->partNumber = part->partNumber; + _data->tileOffsetsPosition = part->chunkOffsetTablePosition; + _data->previewPosition = part->previewPosition; + _data->multipart = part->multipart; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + if (_data) delete _data; + + REPLACE_EXC (e, "Cannot initialize output part " + "\"" << part->partNumber << "\". " << e.what()); + throw; + } + catch (...) + { + if (_data) delete _data; + + throw; + } +} + +void +DeepTiledOutputFile::initialize (const Header &header) +{ + _data->header = header; + _data->header.setType(DEEPTILE); + _data->lineOrder = _data->header.lineOrder(); + + // + // Check that the file is indeed tiled + // + + _data->tileDesc = _data->header.tileDescription(); + + // + // Save the dataWindow information + // + + const Box2i &dataWindow = _data->header.dataWindow(); + _data->minX = dataWindow.min.x; + _data->maxX = dataWindow.max.x; + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; + + // + // Precompute level and tile information to speed up utility functions + // + + precalculateTileInfo (_data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + _data->numXTiles, _data->numYTiles, + _data->numXLevels, _data->numYLevels); + + // + // Determine the first tile coordinate that we will be writing + // if the file is not RANDOM_Y. + // + + _data->nextTileToWrite = (_data->lineOrder == INCREASING_Y)? + TileCoord (0, 0, 0, 0): + TileCoord (0, _data->numYTiles[0] - 1, 0, 0); + + Compressor* compressor = newTileCompressor + (_data->header.compression(), + 0, + _data->tileDesc.ySize, + _data->header); + + _data->format = defaultFormat (compressor); + + if (compressor != 0) + delete compressor; + + _data->tileOffsets = TileOffsets (_data->tileDesc.mode, + _data->numXLevels, + _data->numYLevels, + _data->numXTiles, + _data->numYTiles); + + //ignore the existing value of chunkCount - correct it if it's wrong + _data->header.setChunkCount(getChunkOffsetTableSize(_data->header,true)); + + _data->maxSampleCountTableSize = _data->tileDesc.ySize * + _data->tileDesc.xSize * + sizeof(int); + + + for (size_t i = 0; i < _data->tileBuffers.size(); i++) + { + _data->tileBuffers[i] = new TileBuffer (); + + _data->tileBuffers[i]->sampleCountTableBuffer. + resizeErase(_data->maxSampleCountTableSize); + + char * p = &(_data->tileBuffers[i]->sampleCountTableBuffer[0]); + memset (p, 0, _data->maxSampleCountTableSize); + + _data->tileBuffers[i]->sampleCountTableCompressor = + newCompressor (_data->header.compression(), + _data->maxSampleCountTableSize, + _data->header); + } +} + + +DeepTiledOutputFile::~DeepTiledOutputFile () +{ + if (_data) + { + { + Lock lock(*_data->_streamData); + Int64 originalPosition = _data->_streamData->os->tellp(); + + if (_data->tileOffsetsPosition > 0) + { + try + { + _data->_streamData->os->seekp (_data->tileOffsetsPosition); + _data->tileOffsets.writeTo (*_data->_streamData->os); + + // + // Restore the original position. + // + _data->_streamData->os->seekp (originalPosition); + } + catch (...) + { + // + // We cannot safely throw any exceptions from here. + // This destructor may have been called because the + // stack is currently being unwound for another + // exception. + // + } + } + } + + if (_data->_deleteStream && _data->_streamData) + delete _data->_streamData->os; + + // + // (TODO) we should have a way to tell if the stream data is owned by + // this file or by a parent multipart file. + // + + if (_data->partNumber == -1 && _data->_streamData) + delete _data->_streamData; + + delete _data; + } +} + + +const char * +DeepTiledOutputFile::fileName () const +{ + return _data->_streamData->os->fileName(); +} + + +const Header & +DeepTiledOutputFile::header () const +{ + return _data->header; +} + + +void +DeepTiledOutputFile::setFrameBuffer (const DeepFrameBuffer &frameBuffer) +{ + Lock lock (*_data->_streamData); + + // + // Check if the new frame buffer descriptor + // is compatible with the image file header. + // + + const ChannelList &channels = _data->header.channels(); + + for (ChannelList::ConstIterator i = channels.begin(); + i != channels.end(); + ++i) + { + DeepFrameBuffer::ConstIterator j = frameBuffer.find (i.name()); + + if (j == frameBuffer.end()) + continue; + + if (i.channel().type != j.slice().type) + THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" channel " + "of output file \"" << fileName() << "\" is " + "not compatible with the frame buffer's " + "pixel type."); + + if (j.slice().xSampling != 1 || j.slice().ySampling != 1) + THROW (IEX_NAMESPACE::ArgExc, "All channels in a tiled file must have" + "sampling (1,1)."); + } + + // + // Store the pixel sample count table. + // + + const Slice& sampleCountSlice = frameBuffer.getSampleCountSlice(); + if (sampleCountSlice.base == 0) + { + throw IEX_NAMESPACE::ArgExc ("Invalid base pointer, please set a proper sample count slice."); + } + else + { + _data->sampleCountSliceBase = sampleCountSlice.base; + _data->sampleCountXStride = sampleCountSlice.xStride; + _data->sampleCountYStride = sampleCountSlice.yStride; + _data->sampleCountXTileCoords = sampleCountSlice.xTileCoords; + _data->sampleCountYTileCoords = sampleCountSlice.yTileCoords; + } + + // + // Initialize slice table for writePixels(). + // Pixel sample count slice is not presented in the header, + // so it wouldn't be added here. + // Store the pixel base pointer table. + // + + vector slices; + + for (ChannelList::ConstIterator i = channels.begin(); + i != channels.end(); + ++i) + { + DeepFrameBuffer::ConstIterator j = frameBuffer.find (i.name()); + + if (j == frameBuffer.end()) + { + // + // Channel i is not present in the frame buffer. + // In the file, channel i will contain only zeroes. + // + + slices.push_back (new TOutSliceInfo (i.channel().type, + 0, // sampleStride, + 0, // xStride + 0, // yStride + true)); // zero + } + else + { + // + // Channel i is present in the frame buffer. + // + + slices.push_back (new TOutSliceInfo (j.slice().type, + j.slice().sampleStride, + j.slice().xStride, + j.slice().yStride, + false, // zero + (j.slice().xTileCoords)? 1: 0, + (j.slice().yTileCoords)? 1: 0)); + + TOutSliceInfo* slice = slices.back(); + slice->base = j.slice().base; + + } + } + + // + // Store the new frame buffer. + // + + _data->frameBuffer = frameBuffer; + + for (size_t i = 0; i < _data->slices.size(); i++) + delete _data->slices[i]; + _data->slices = slices; +} + + +const DeepFrameBuffer & +DeepTiledOutputFile::frameBuffer () const +{ + Lock lock (*_data->_streamData); + return _data->frameBuffer; +} + + +void +DeepTiledOutputFile::writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly) +{ + try + { + Lock lock (*_data->_streamData); + + if (_data->slices.size() == 0) + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data source."); + + if (!isValidTile (dx1, dy1, lx, ly) || !isValidTile (dx2, dy2, lx, ly)) + throw IEX_NAMESPACE::ArgExc ("Tile coordinates are invalid."); + + if (!isValidLevel (lx, ly)) + THROW (IEX_NAMESPACE::ArgExc, + "Level coordinate " + "(" << lx << ", " << ly << ") " + "is invalid."); + // + // Determine the first and last tile coordinates in both dimensions + // based on the file's lineOrder + // + + if (dx1 > dx2) + swap (dx1, dx2); + + if (dy1 > dy2) + swap (dy1, dy2); + + int dyStart = dy1; + int dyStop = dy2 + 1; + int dY = 1; + + if (_data->lineOrder == DECREASING_Y) + { + dyStart = dy2; + dyStop = dy1 - 1; + dY = -1; + } + + int numTiles = (dx2 - dx1 + 1) * (dy2 - dy1 + 1); + int numTasks = min ((int)_data->tileBuffers.size(), numTiles); + + // + // Create a task group for all tile buffer tasks. When the + // task group goes out of scope, the destructor waits until + // all tasks are complete. + // + + { + TaskGroup taskGroup; + + // + // Add in the initial compression tasks to the thread pool + // + + int nextCompBuffer = 0; + int dxComp = dx1; + int dyComp = dyStart; + + while (nextCompBuffer < numTasks) + { + ThreadPool::addGlobalTask (new TileBufferTask (&taskGroup, + _data, + nextCompBuffer++, + dxComp, dyComp, + lx, ly)); + dxComp++; + + if (dxComp > dx2) + { + dxComp = dx1; + dyComp += dY; + } + } + + // + // Write the compressed buffers and add in more compression + // tasks until done + // + + int nextWriteBuffer = 0; + int dxWrite = dx1; + int dyWrite = dyStart; + + while (nextWriteBuffer < numTiles) + { + // + // Wait until the nextWriteBuffer is ready to be written + // + + TileBuffer* writeBuffer = + _data->getTileBuffer (nextWriteBuffer); + + writeBuffer->wait(); + + // + // Write the tilebuffer + // + + bufferedTileWrite ( _data, dxWrite, dyWrite, lx, ly, + writeBuffer->dataPtr, + writeBuffer->dataSize, + writeBuffer->uncompressedSize, + writeBuffer->sampleCountTablePtr, + writeBuffer->sampleCountTableSize); + + // + // Release the lock on nextWriteBuffer + // + + writeBuffer->post(); + + // + // If there are no more tileBuffers to compress, then + // only continue to write out remaining tileBuffers, + // otherwise keep adding compression tasks. + // + + if (nextCompBuffer < numTiles) + { + // + // add nextCompBuffer as a compression Task + // + + ThreadPool::addGlobalTask + (new TileBufferTask (&taskGroup, + _data, + nextCompBuffer, + dxComp, dyComp, + lx, ly)); + } + + nextWriteBuffer++; + dxWrite++; + + if (dxWrite > dx2) + { + dxWrite = dx1; + dyWrite += dY; + } + + nextCompBuffer++; + dxComp++; + + if (dxComp > dx2) + { + dxComp = dx1; + dyComp += dY; + } + } + + // + // finish all tasks + // + } + + // + // Exeption handling: + // + // TileBufferTask::execute() may have encountered exceptions, but + // those exceptions occurred in another thread, not in the thread + // that is executing this call to TiledOutputFile::writeTiles(). + // TileBufferTask::execute() has caught all exceptions and stored + // the exceptions' what() strings in the tile buffers. + // Now we check if any tile buffer contains a stored exception; if + // this is the case then we re-throw the exception in this thread. + // (It is possible that multiple tile buffers contain stored + // exceptions. We re-throw the first exception we find and + // ignore all others.) + // + + const string *exception = 0; + + for (size_t i = 0; i < _data->tileBuffers.size(); ++i) + { + TileBuffer *tileBuffer = _data->tileBuffers[i]; + + if (tileBuffer->hasException && !exception) + exception = &tileBuffer->exception; + + tileBuffer->hasException = false; + } + + if (exception) + throw IEX_NAMESPACE::IoExc (*exception); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Failed to write pixel data to image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +void +DeepTiledOutputFile::writeTiles (int dx1, int dxMax, int dyMin, int dyMax, int l) +{ + writeTiles (dx1, dxMax, dyMin, dyMax, l, l); +} + + +void +DeepTiledOutputFile::writeTile (int dx, int dy, int lx, int ly) +{ + writeTiles (dx, dx, dy, dy, lx, ly); +} + + +void +DeepTiledOutputFile::writeTile (int dx, int dy, int l) +{ + writeTile(dx, dy, l, l); +} + + +void +DeepTiledOutputFile::copyPixels (DeepTiledInputFile &in) +{ + + // + // Check if this file's and and the InputFile's + // headers are compatible. + // + + const Header &hdr = _data->header; + const Header &inHdr = in.header(); + + + + if (!(hdr.tileDescription() == inHdr.tileDescription())) + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files have different tile descriptions."); + + if (!(hdr.dataWindow() == inHdr.dataWindow())) + THROW (IEX_NAMESPACE::ArgExc, "Cannot copy pixels from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\". The " + "files have different data windows."); + + if (!(hdr.lineOrder() == inHdr.lineOrder())) + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files have different line orders."); + + if (!(hdr.compression() == inHdr.compression())) + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files use different compression methods."); + + if (!(hdr.channels() == inHdr.channels())) + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" " + "failed. The files have different channel " + "lists."); + + + // Verify that no pixel data have been written to this file yet. + // + + if (!_data->tileOffsets.isEmpty()) + THROW (IEX_NAMESPACE::LogicExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << _data->_streamData->os->fileName() << "\" " + "failed. \"" << fileName() << "\" " + "already contains pixel data."); + + + int numAllTiles = in.totalTiles(); + + Lock lock (*_data->_streamData); + + // + // special handling for random tiles + // + + vector dx_list(_data->lineOrder==RANDOM_Y ? numAllTiles : 1); + vector dy_list(_data->lineOrder==RANDOM_Y ? numAllTiles : 1); + vector lx_list(_data->lineOrder==RANDOM_Y ? numAllTiles : 1); + vector ly_list(_data->lineOrder==RANDOM_Y ? numAllTiles : 1); + + if(_data->lineOrder==RANDOM_Y) + { + in.getTileOrder(&dx_list[0],&dy_list[0],&lx_list[0],&ly_list[0]); + _data->nextTileToWrite.dx=dx_list[0]; + _data->nextTileToWrite.dy=dy_list[0]; + _data->nextTileToWrite.lx=lx_list[0]; + _data->nextTileToWrite.ly=ly_list[0]; + } + + + vector data(4096); + for (int i = 0; i < numAllTiles; ++i) + { + + int dx = _data->nextTileToWrite.dx; + int dy = _data->nextTileToWrite.dy; + int lx = _data->nextTileToWrite.lx; + int ly = _data->nextTileToWrite.ly; + + Int64 dataSize = data.size(); + + in.rawTileData (dx, dy, lx, ly, &data[0], dataSize); + if(dataSize>data.size()) + { + data.resize(dataSize); + in.rawTileData (dx, dy, lx, ly, &data[0], dataSize); + } + Int64 sampleCountTableSize = *(Int64 *)(&data[0] + 16); + Int64 pixelDataSize = *(Int64 *)(&data[0] + 24); + Int64 unpackedPixelDataSize = *(Int64 *)(&data[0] + 32); + char * sampleCountTable = &data[0]+40; + char * pixelData = sampleCountTable + sampleCountTableSize; + + writeTileData (_data, dx, dy, lx, ly, pixelData, pixelDataSize,unpackedPixelDataSize,sampleCountTable,sampleCountTableSize); + + + if(_data->lineOrder==RANDOM_Y) + { + if(inextTileToWrite.dx=dx_list[i+1]; + _data->nextTileToWrite.dy=dy_list[i+1]; + _data->nextTileToWrite.lx=lx_list[i+1]; + _data->nextTileToWrite.ly=ly_list[i+1]; + } + }else{ + _data->nextTileToWrite = _data->nextTileCoord (_data->nextTileToWrite); + } + + } +} + + +void +DeepTiledOutputFile::copyPixels (DeepTiledInputPart &in) +{ + copyPixels(*in.file); +} + + +unsigned int +DeepTiledOutputFile::tileXSize () const +{ + return _data->tileDesc.xSize; +} + + +unsigned int +DeepTiledOutputFile::tileYSize () const +{ + return _data->tileDesc.ySize; +} + + +LevelMode +DeepTiledOutputFile::levelMode () const +{ + return _data->tileDesc.mode; +} + + +LevelRoundingMode +DeepTiledOutputFile::levelRoundingMode () const +{ + return _data->tileDesc.roundingMode; +} + + +int +DeepTiledOutputFile::numLevels () const +{ + if (levelMode() == RIPMAP_LEVELS) + THROW (IEX_NAMESPACE::LogicExc, "Error calling numLevels() on image " + "file \"" << fileName() << "\" " + "(numLevels() is not defined for RIPMAPs)."); + return _data->numXLevels; +} + + +int +DeepTiledOutputFile::numXLevels () const +{ + return _data->numXLevels; +} + + +int +DeepTiledOutputFile::numYLevels () const +{ + return _data->numYLevels; +} + + +bool +DeepTiledOutputFile::isValidLevel (int lx, int ly) const +{ + if (lx < 0 || ly < 0) + return false; + + if (levelMode() == MIPMAP_LEVELS && lx != ly) + return false; + + if (lx >= numXLevels() || ly >= numYLevels()) + return false; + + return true; +} + + +int +DeepTiledOutputFile::levelWidth (int lx) const +{ + try + { + int retVal = levelSize (_data->minX, _data->maxX, lx, + _data->tileDesc.roundingMode); + + return retVal; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error calling levelWidth() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +int +DeepTiledOutputFile::levelHeight (int ly) const +{ + try + { + return levelSize (_data->minY, _data->maxY, ly, + _data->tileDesc.roundingMode); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error calling levelHeight() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +int +DeepTiledOutputFile::numXTiles (int lx) const +{ + if (lx < 0 || lx >= _data->numXLevels) + THROW (IEX_NAMESPACE::LogicExc, "Error calling numXTiles() on image " + "file \"" << _data->_streamData->os->fileName() << "\" " + "(Argument is not in valid range)."); + + return _data->numXTiles[lx]; +} + + +int +DeepTiledOutputFile::numYTiles (int ly) const +{ + if (ly < 0 || ly >= _data->numYLevels) + THROW (IEX_NAMESPACE::LogicExc, "Error calling numXTiles() on image " + "file \"" << _data->_streamData->os->fileName() << "\" " + "(Argument is not in valid range)."); + + return _data->numYTiles[ly]; +} + + +Box2i +DeepTiledOutputFile::dataWindowForLevel (int l) const +{ + return dataWindowForLevel (l, l); +} + + +Box2i +DeepTiledOutputFile::dataWindowForLevel (int lx, int ly) const +{ + try + { + return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForLevel ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + lx, ly); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error calling dataWindowForLevel() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +Box2i +DeepTiledOutputFile::dataWindowForTile (int dx, int dy, int l) const +{ + return dataWindowForTile (dx, dy, l, l); +} + + +Box2i +DeepTiledOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const +{ + try + { + if (!isValidTile (dx, dy, lx, ly)) + throw IEX_NAMESPACE::ArgExc ("Arguments not in valid range."); + + return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + dx, dy, + lx, ly); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error calling dataWindowForTile() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +bool +DeepTiledOutputFile::isValidTile (int dx, int dy, int lx, int ly) const +{ + return ((lx < _data->numXLevels && lx >= 0) && + (ly < _data->numYLevels && ly >= 0) && + (dx < _data->numXTiles[lx] && dx >= 0) && + (dy < _data->numYTiles[ly] && dy >= 0)); +} + + +void +DeepTiledOutputFile::updatePreviewImage (const PreviewRgba newPixels[]) +{ + Lock lock (*_data->_streamData); + + if (_data->previewPosition <= 0) + THROW (IEX_NAMESPACE::LogicExc, "Cannot update preview image pixels. " + "File \"" << fileName() << "\" does not " + "contain a preview image."); + + // + // Store the new pixels in the header's preview image attribute. + // + + PreviewImageAttribute &pia = + _data->header.typedAttribute ("preview"); + + PreviewImage &pi = pia.value(); + PreviewRgba *pixels = pi.pixels(); + int numPixels = pi.width() * pi.height(); + + for (int i = 0; i < numPixels; ++i) + pixels[i] = newPixels[i]; + + // + // Save the current file position, jump to the position in + // the file where the preview image starts, store the new + // preview image, and jump back to the saved file position. + // + + Int64 savedPosition = _data->_streamData->os->tellp(); + + try + { + _data->_streamData->os->seekp (_data->previewPosition); + pia.writeValueTo (*_data->_streamData->os, _data->version); + _data->_streamData->os->seekp (savedPosition); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Cannot update preview image pixels for " + "file \"" << fileName() << "\". " << e.what()); + throw; + } +} + + +void +DeepTiledOutputFile::breakTile + (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c) +{ + Lock lock (*_data->_streamData); + + Int64 position = _data->tileOffsets (dx, dy, lx, ly); + + if (!position) + THROW (IEX_NAMESPACE::ArgExc, + "Cannot overwrite tile " + "(" << dx << ", " << dy << ", " << lx << "," << ly << "). " + "The tile has not yet been stored in " + "file \"" << fileName() << "\"."); + + _data->_streamData->currentPosition = 0; + _data->_streamData->os->seekp (position + offset); + + for (int i = 0; i < length; ++i) + _data->_streamData->os->write (&c, 1); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepTiledOutputFile.h b/3rdparty/openexr/IlmImf/ImfDeepTiledOutputFile.h new file mode 100644 index 0000000000..fa76a691e6 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepTiledOutputFile.h @@ -0,0 +1,506 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#ifndef INCLUDED_IMF_DEEP_TILED_OUTPUT_FILE_H +#define INCLUDED_IMF_DEEP_TILED_OUTPUT_FILE_H + +//----------------------------------------------------------------------------- +// +// class DeepTiledOutputFile +// +//----------------------------------------------------------------------------- + +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImathBox.h" +#include "ImfThreading.h" +#include "ImfGenericOutputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class DeepTiledOutputFile : public GenericOutputFile +{ + public: + + //------------------------------------------------------------------- + // A constructor that opens the file with the specified name, and + // writes the file header. The file header is also copied into the + // TiledOutputFile object, and can later be accessed via the header() + // method. + // + // Destroying TiledOutputFile constructed with this constructor + // automatically closes the corresponding files. + // + // The header must contain a TileDescriptionAttribute called "tiles". + // + // The x and y subsampling factors for all image channels must be 1; + // subsampling is not supported. + // + // Tiles can be written to the file in arbitrary order. The line + // order attribute can be used to cause the tiles to be sorted in + // the file. When the file is read later, reading the tiles in the + // same order as they are in the file tends to be significantly + // faster than reading the tiles in random order (see writeTile, + // below). + //------------------------------------------------------------------- + + IMF_EXPORT + DeepTiledOutputFile (const char fileName[], + const Header &header, + int numThreads = globalThreadCount ()); + + + // ---------------------------------------------------------------- + // A constructor that attaches the new TiledOutputFile object to + // a file that has already been opened. Destroying TiledOutputFile + // objects constructed with this constructor does not automatically + // close the corresponding files. + // ---------------------------------------------------------------- + + IMF_EXPORT + DeepTiledOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + int numThreads = globalThreadCount ()); + + + //----------------------------------------------------- + // Destructor + // + // Destroying a TiledOutputFile object before all tiles + // have been written results in an incomplete file. + //----------------------------------------------------- + + IMF_EXPORT + virtual ~DeepTiledOutputFile (); + + + //------------------------ + // Access to the file name + //------------------------ + + IMF_EXPORT + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + IMF_EXPORT + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledOutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writeTile() is + // called. The current frame buffer can be changed + // after each call to writeTile(). + //------------------------------------------------------- + + IMF_EXPORT + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + IMF_EXPORT + const DeepFrameBuffer & frameBuffer () const; + + + //------------------- + // Utility functions: + //------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + IMF_EXPORT + unsigned int tileXSize () const; + IMF_EXPORT + unsigned int tileYSize () const; + IMF_EXPORT + LevelMode levelMode () const; + IMF_EXPORT + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with MIPMAP_LEVELS + // files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + //-------------------------------------------------------------------- + + IMF_EXPORT + int numLevels () const; + IMF_EXPORT + int numXLevels () const; + IMF_EXPORT + int numYLevels () const; + IMF_EXPORT + bool isValidLevel (int lx, int ly) const; + + + //--------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //--------------------------------------------------------- + + IMF_EXPORT + int levelWidth (int lx) const; + IMF_EXPORT + int levelHeight (int ly) const; + + + //---------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //---------------------------------------------------------- + + IMF_EXPORT + int numXTiles (int lx = 0) const; + IMF_EXPORT + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a level with + // level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------------ + // Write pixel data: + // + // writeTile(dx, dy, lx, ly) writes the tile with tile + // coordinates (dx, dy), and level number (lx, ly) to + // the file. + // + // dx must lie in the interval [0, numXTiles(lx) - 1] + // dy must lie in the interval [0, numYTiles(ly) - 1] + // + // lx must lie in the interval [0, numXLevels() - 1] + // ly must lie in the inverval [0, numYLevels() - 1] + // + // writeTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls + // writeTile(dx, dy, level, level). + // + // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow + // writing multiple tiles at once. If multi-threading is used + // multiple tiles are written concurrently. The tile coordinates, + // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile + // coordinates. It is valid for dx1 < dx2 or dy1 < dy2; the + // tiles are always written in the order specified by the line + // order attribute. Hence, it is not possible to specify an + // "invalid" or empty tile range. + // + // Pixels that are outside the pixel coordinate range for the tile's + // level, are never accessed by writeTile(). + // + // Each tile in the file must be written exactly once. + // + // The file's line order attribute determines the order of the tiles + // in the file: + // + // INCREASING_Y In the file, the tiles for each level are stored + // in a contiguous block. The levels are ordered + // like this: + // + // (0, 0) (1, 0) ... (nx-1, 0) + // (0, 1) (1, 1) ... (nx-1, 1) + // ... + // (0,ny-1) (1,ny-1) ... (nx-1,ny-1) + // + // where nx = numXLevels(), and ny = numYLevels(). + // In an individual level, (lx, ly), the tiles + // are stored in the following order: + // + // (0, 0) (1, 0) ... (tx-1, 0) + // (0, 1) (1, 1) ... (tx-1, 1) + // ... + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // + // where tx = numXTiles(lx), + // and ty = numYTiles(ly). + // + // DECREASING_Y As for INCREASING_Y, the tiles for each level + // are stored in a contiguous block. The levels + // are ordered the same way as for INCREASING_Y, + // but within an individual level, the tiles + // are stored in this order: + // + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // ... + // (0, 1) (1, 1) ... (tx-1, 1) + // (0, 0) (1, 0) ... (tx-1, 0) + // + // + // RANDOM_Y The order of the calls to writeTile() determines + // the order of the tiles in the file. + // + //------------------------------------------------------------------ + + IMF_EXPORT + void writeTile (int dx, int dy, int l = 0); + IMF_EXPORT + void writeTile (int dx, int dy, int lx, int ly); + + IMF_EXPORT + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + IMF_EXPORT + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //------------------------------------------------------------------ + // Shortcut to copy all pixels from a TiledInputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the TiledInputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder", "channels", and "tiles" attributes must be the same. + //------------------------------------------------------------------ + + IMF_EXPORT + void copyPixels (DeepTiledInputFile &in); + IMF_EXPORT + void copyPixels (DeepTiledInputPart &in); + + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few tiles at a time, + // while the image is being generated. Since the preview image + // is an attribute in the file's header, it gets stored in the + // file as soon as the file is opened, but we may not know what + // the preview image should look like until we have written the + // last tile of the main image. + // + //-------------------------------------------------------------- + + IMF_EXPORT + void updatePreviewImage (const PreviewRgba newPixels[]); + + + //------------------------------------------------------------- + // Break a tile -- for testing and debugging only: + // + // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the + // output file by writing n copies of character c, starting + // p bytes from the beginning of the tile with tile coordinates + // (dx, dy) and level number (lx, ly). + // + // Warning: Calling this function usually results in a broken + // image file. The file or parts of it may not be readable, + // or the file may contain bad data. + // + //------------------------------------------------------------- + + IMF_EXPORT + void breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c); + struct Data; + + private: + + // ---------------------------------------------------------------- + // A constructor attaches the OutputStreamMutex to the + // given one from MultiPartOutputFile. Set the previewPosition + // and lineOffsetsPosition which have been acquired from + // the constructor of MultiPartOutputFile as well. + // ---------------------------------------------------------------- + DeepTiledOutputFile (const OutputPartData* part); + + DeepTiledOutputFile (const DeepTiledOutputFile &); // not implemented + DeepTiledOutputFile & operator = (const DeepTiledOutputFile &); // not implemented + + void initialize (const Header &header); + + bool isValidTile (int dx, int dy, + int lx, int ly) const; + + size_t bytesPerLineForTile (int dx, int dy, + int lx, int ly) const; + + Data * _data; + + + friend class MultiPartOutputFile; + +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfDeepTiledOutputPart.cpp b/3rdparty/openexr/IlmImf/ImfDeepTiledOutputPart.cpp new file mode 100644 index 0000000000..7239c01fe0 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepTiledOutputPart.cpp @@ -0,0 +1,250 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfDeepTiledOutputPart.h" +#include "ImfMultiPartOutputFile.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +DeepTiledOutputPart::DeepTiledOutputPart(MultiPartOutputFile& multiPartFile, int partNumber) +{ + file = multiPartFile.getOutputPart(partNumber); +} + +const char * +DeepTiledOutputPart::fileName () const +{ + return file->fileName(); +} + + +const Header & +DeepTiledOutputPart::header () const +{ + return file->header(); +} + + +void +DeepTiledOutputPart::setFrameBuffer (const DeepFrameBuffer &frameBuffer) +{ + file->setFrameBuffer(frameBuffer); +} + + +const DeepFrameBuffer & +DeepTiledOutputPart::frameBuffer () const +{ + return file->frameBuffer(); +} + + +unsigned int +DeepTiledOutputPart::tileXSize () const +{ + return file->tileXSize(); +} + + +unsigned int +DeepTiledOutputPart::tileYSize () const +{ + return file->tileYSize(); +} + + +LevelMode +DeepTiledOutputPart::levelMode () const +{ + return file->levelMode(); +} + + +LevelRoundingMode +DeepTiledOutputPart::levelRoundingMode () const +{ + return file->levelRoundingMode(); +} + + +int +DeepTiledOutputPart::numLevels () const +{ + return file->numLevels(); +} + + +int +DeepTiledOutputPart::numXLevels () const +{ + return file->numXLevels(); +} + + +int +DeepTiledOutputPart::numYLevels () const +{ + return file->numYLevels(); +} + + +bool +DeepTiledOutputPart::isValidLevel (int lx, int ly) const +{ + return file->isValidLevel(lx, ly); +} + + +int +DeepTiledOutputPart::levelWidth (int lx) const +{ + return file->levelWidth(lx); +} + + +int +DeepTiledOutputPart::levelHeight (int ly) const +{ + return file->levelHeight(ly); +} + + +int +DeepTiledOutputPart::numXTiles (int lx) const +{ + return file->numXTiles(lx); +} + + +int +DeepTiledOutputPart::numYTiles (int ly) const +{ + return file->numYTiles(ly); +} + + + +IMATH_NAMESPACE::Box2i +DeepTiledOutputPart::dataWindowForLevel (int l) const +{ + return file->dataWindowForLevel(l); +} + + +IMATH_NAMESPACE::Box2i +DeepTiledOutputPart::dataWindowForLevel (int lx, int ly) const +{ + return file->dataWindowForLevel(lx, ly); +} + + +IMATH_NAMESPACE::Box2i +DeepTiledOutputPart::dataWindowForTile (int dx, int dy, + int l) const +{ + return file->dataWindowForTile(dx, dy, l); +} + + +IMATH_NAMESPACE::Box2i +DeepTiledOutputPart::dataWindowForTile (int dx, int dy, + int lx, int ly) const +{ + return file->dataWindowForTile(dx, dy, lx, ly); +} + + +void +DeepTiledOutputPart::writeTile (int dx, int dy, int l) +{ + file->writeTile(dx, dy, l); +} + + +void +DeepTiledOutputPart::writeTile (int dx, int dy, int lx, int ly) +{ + file->writeTile(dx, dy, lx, ly); +} + + +void +DeepTiledOutputPart::writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly) +{ + file->writeTiles(dx1, dx2, dy1, dy2, lx, ly); +} + + +void +DeepTiledOutputPart::writeTiles (int dx1, int dx2, int dy1, int dy2, + int l) +{ + file->writeTiles(dx1, dx2, dy1, dy2, l); +} + + +void +DeepTiledOutputPart::copyPixels (DeepTiledInputFile &in) +{ + file->copyPixels(in); +} + + +void +DeepTiledOutputPart::copyPixels (DeepTiledInputPart &in) +{ + file->copyPixels(in); +} + + +void +DeepTiledOutputPart::updatePreviewImage (const PreviewRgba newPixels[]) +{ + file->updatePreviewImage(newPixels); +} + + +void +DeepTiledOutputPart::breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c) +{ + file->breakTile(dx, dy, lx, ly, offset, length, c); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDeepTiledOutputPart.h b/3rdparty/openexr/IlmImf/ImfDeepTiledOutputPart.h new file mode 100644 index 0000000000..8b436562d2 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDeepTiledOutputPart.h @@ -0,0 +1,423 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFDEEPTILEDOUTPUTPART_H_ +#define IMFDEEPTILEDOUTPUTPART_H_ + +#include "ImfForward.h" +#include "ImfDeepTiledInputFile.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class DeepTiledOutputPart +{ + public: + + IMF_EXPORT + DeepTiledOutputPart(MultiPartOutputFile& multiPartFile, int partNumber); + + //------------------------ + // Access to the file name + //------------------------ + + IMF_EXPORT + const char * fileName () const; + + + //-------------------------- + // Access to the file header + //-------------------------- + + IMF_EXPORT + const Header & header () const; + + + //------------------------------------------------------- + // Set the current frame buffer -- copies the FrameBuffer + // object into the TiledOutputFile object. + // + // The current frame buffer is the source of the pixel + // data written to the file. The current frame buffer + // must be set at least once before writeTile() is + // called. The current frame buffer can be changed + // after each call to writeTile(). + //------------------------------------------------------- + + IMF_EXPORT + void setFrameBuffer (const DeepFrameBuffer &frameBuffer); + + + //----------------------------------- + // Access to the current frame buffer + //----------------------------------- + + IMF_EXPORT + const DeepFrameBuffer & frameBuffer () const; + + + //------------------- + // Utility functions: + //------------------- + + //--------------------------------------------------------- + // Multiresolution mode and tile size: + // The following functions return the xSize, ySize and mode + // fields of the file header's TileDescriptionAttribute. + //--------------------------------------------------------- + + IMF_EXPORT + unsigned int tileXSize () const; + IMF_EXPORT + unsigned int tileYSize () const; + IMF_EXPORT + LevelMode levelMode () const; + IMF_EXPORT + LevelRoundingMode levelRoundingMode () const; + + + //-------------------------------------------------------------------- + // Number of levels: + // + // numXLevels() returns the file's number of levels in x direction. + // + // if levelMode() == ONE_LEVEL: + // return value is: 1 + // + // if levelMode() == MIPMAP_LEVELS: + // return value is: rfunc (log (max (w, h)) / log (2)) + 1 + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (w) / log (2)) + 1 + // + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // + // numYLevels() returns the file's number of levels in y direction. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // return value is: rfunc (log (h) / log (2)) + 1 + // + // + // numLevels() is a convenience function for use with MIPMAP_LEVELS + // files. + // + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // return value is the same as for numXLevels() + // + // if levelMode() == RIPMAP_LEVELS: + // an IEX_NAMESPACE::LogicExc exception is thrown + // + // isValidLevel(lx, ly) returns true if the file contains + // a level with level number (lx, ly), false if not. + // + //-------------------------------------------------------------------- + + IMF_EXPORT + int numLevels () const; + IMF_EXPORT + int numXLevels () const; + IMF_EXPORT + int numYLevels () const; + IMF_EXPORT + bool isValidLevel (int lx, int ly) const; + + + //--------------------------------------------------------- + // Dimensions of a level: + // + // levelWidth(lx) returns the width of a level with level + // number (lx, *), where * is any number. + // + // return value is: + // max (1, rfunc (w / pow (2, lx))) + // + // + // levelHeight(ly) returns the height of a level with level + // number (*, ly), where * is any number. + // + // return value is: + // max (1, rfunc (h / pow (2, ly))) + // + //--------------------------------------------------------- + + IMF_EXPORT + int levelWidth (int lx) const; + IMF_EXPORT + int levelHeight (int ly) const; + + + //---------------------------------------------------------- + // Number of tiles: + // + // numXTiles(lx) returns the number of tiles in x direction + // that cover a level with level number (lx, *), where * is + // any number. + // + // return value is: + // (levelWidth(lx) + tileXSize() - 1) / tileXSize() + // + // + // numYTiles(ly) returns the number of tiles in y direction + // that cover a level with level number (*, ly), where * is + // any number. + // + // return value is: + // (levelHeight(ly) + tileXSize() - 1) / tileXSize() + // + //---------------------------------------------------------- + + IMF_EXPORT + int numXTiles (int lx = 0) const; + IMF_EXPORT + int numYTiles (int ly = 0) const; + + + //--------------------------------------------------------- + // Level pixel ranges: + // + // dataWindowForLevel(lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a level with + // level number (lx, ly) + // + // return value is a Box2i with min value: + // (dataWindow.min.x, dataWindow.min.y) + // + // and max value: + // (dataWindow.min.x + levelWidth(lx) - 1, + // dataWindow.min.y + levelHeight(ly) - 1) + // + // dataWindowForLevel(level) is a convenience function used + // for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForLevel(level, level). + // + //--------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + + + //------------------------------------------------------------------- + // Tile pixel ranges: + // + // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional + // region of valid pixel coordinates for a tile with tile coordinates + // (dx,dy) and level number (lx, ly). + // + // return value is a Box2i with min value: + // (dataWindow.min.x + dx * tileXSize(), + // dataWindow.min.y + dy * tileYSize()) + // + // and max value: + // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, + // dataWindow.min.y + (dy + 1) * tileYSize() - 1) + // + // dataWindowForTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns + // dataWindowForTile(dx, dy, level, level). + // + //------------------------------------------------------------------- + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + + //------------------------------------------------------------------ + // Write pixel data: + // + // writeTile(dx, dy, lx, ly) writes the tile with tile + // coordinates (dx, dy), and level number (lx, ly) to + // the file. + // + // dx must lie in the interval [0, numXTiles(lx) - 1] + // dy must lie in the interval [0, numYTiles(ly) - 1] + // + // lx must lie in the interval [0, numXLevels() - 1] + // ly must lie in the inverval [0, numYLevels() - 1] + // + // writeTile(dx, dy, level) is a convenience function + // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls + // writeTile(dx, dy, level, level). + // + // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow + // writing multiple tiles at once. If multi-threading is used + // multiple tiles are written concurrently. The tile coordinates, + // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile + // coordinates. It is valid for dx1 < dx2 or dy1 < dy2; the + // tiles are always written in the order specified by the line + // order attribute. Hence, it is not possible to specify an + // "invalid" or empty tile range. + // + // Pixels that are outside the pixel coordinate range for the tile's + // level, are never accessed by writeTile(). + // + // Each tile in the file must be written exactly once. + // + // The file's line order attribute determines the order of the tiles + // in the file: + // + // INCREASING_Y In the file, the tiles for each level are stored + // in a contiguous block. The levels are ordered + // like this: + // + // (0, 0) (1, 0) ... (nx-1, 0) + // (0, 1) (1, 1) ... (nx-1, 1) + // ... + // (0,ny-1) (1,ny-1) ... (nx-1,ny-1) + // + // where nx = numXLevels(), and ny = numYLevels(). + // In an individual level, (lx, ly), the tiles + // are stored in the following order: + // + // (0, 0) (1, 0) ... (tx-1, 0) + // (0, 1) (1, 1) ... (tx-1, 1) + // ... + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // + // where tx = numXTiles(lx), + // and ty = numYTiles(ly). + // + // DECREASING_Y As for INCREASING_Y, the tiles for each level + // are stored in a contiguous block. The levels + // are ordered the same way as for INCREASING_Y, + // but within an individual level, the tiles + // are stored in this order: + // + // (0,ty-1) (1,ty-1) ... (tx-1,ty-1) + // ... + // (0, 1) (1, 1) ... (tx-1, 1) + // (0, 0) (1, 0) ... (tx-1, 0) + // + // + // RANDOM_Y The order of the calls to writeTile() determines + // the order of the tiles in the file. + // + //------------------------------------------------------------------ + + IMF_EXPORT + void writeTile (int dx, int dy, int l = 0); + IMF_EXPORT + void writeTile (int dx, int dy, int lx, int ly); + + IMF_EXPORT + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + + IMF_EXPORT + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + + + //------------------------------------------------------------------ + // Shortcut to copy all pixels from a TiledInputFile into this file, + // without uncompressing and then recompressing the pixel data. + // This file's header must be compatible with the TiledInputFile's + // header: The two header's "dataWindow", "compression", + // "lineOrder", "channels", and "tiles" attributes must be the same. + //------------------------------------------------------------------ + + IMF_EXPORT + void copyPixels (DeepTiledInputFile &in); + IMF_EXPORT + void copyPixels (DeepTiledInputPart &in); + + + + + //-------------------------------------------------------------- + // Updating the preview image: + // + // updatePreviewImage() supplies a new set of pixels for the + // preview image attribute in the file's header. If the header + // does not contain a preview image, updatePreviewImage() throws + // an IEX_NAMESPACE::LogicExc. + // + // Note: updatePreviewImage() is necessary because images are + // often stored in a file incrementally, a few tiles at a time, + // while the image is being generated. Since the preview image + // is an attribute in the file's header, it gets stored in the + // file as soon as the file is opened, but we may not know what + // the preview image should look like until we have written the + // last tile of the main image. + // + //-------------------------------------------------------------- + + IMF_EXPORT + void updatePreviewImage (const PreviewRgba newPixels[]); + + + //------------------------------------------------------------- + // Break a tile -- for testing and debugging only: + // + // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the + // output file by writing n copies of character c, starting + // p bytes from the beginning of the tile with tile coordinates + // (dx, dy) and level number (lx, ly). + // + // Warning: Calling this function usually results in a broken + // image file. The file or parts of it may not be readable, + // or the file may contain bad data. + // + //------------------------------------------------------------- + + IMF_EXPORT + void breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c); + + private: + DeepTiledOutputFile* file; + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFDEEPTILEDOUTPUTPART_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfDoubleAttribute.cpp b/3rdparty/openexr/IlmImf/ImfDoubleAttribute.cpp index 706acde7ca..cbeabe32cf 100644 --- a/3rdparty/openexr/IlmImf/ImfDoubleAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfDoubleAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,7 +43,7 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER template <> @@ -54,4 +54,4 @@ DoubleAttribute::staticTypeName () } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDoubleAttribute.h b/3rdparty/openexr/IlmImf/ImfDoubleAttribute.h index 2208c9bfdf..d9a88a850e 100644 --- a/3rdparty/openexr/IlmImf/ImfDoubleAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfDoubleAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,21 +43,17 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfAttribute.h" +#include "ImfExport.h" - -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER typedef TypedAttribute DoubleAttribute; -template <> const char *DoubleAttribute::staticTypeName (); +template <> IMF_EXPORT const char *DoubleAttribute::staticTypeName (); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif #endif diff --git a/3rdparty/openexr/IlmImf/ImfDwaCompressor.cpp b/3rdparty/openexr/IlmImf/ImfDwaCompressor.cpp new file mode 100644 index 0000000000..7665730a17 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDwaCompressor.cpp @@ -0,0 +1,3439 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2009-2014 DreamWorks Animation LLC. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of DreamWorks Animation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +//--------------------------------------------------- +// +// class DwaCompressor -- Store lossy RGB data by quantizing +// DCT components. +// +// First, we try and figure out what compression strategy to take +// based in channel name. For RGB channels, we want a lossy method +// described below. But, if we have alpha, we should do something +// different (and probably using RLE). If we have depth, or velocity, +// or something else, just fall back to ZIP. The rules for deciding +// which strategy to use are setup in initializeDefaultChannelRules(). +// When writing a file, the relevant rules needed to decode are written +// into the start of the data block, making a self-contained file. +// If initializeDefaultChannelRules() doesn't quite suite your naming +// conventions, you can adjust the rules without breaking decoder +// compatability. +// +// If we're going to lossy compress R, G, or B channels, it's easier +// to toss bits in a more perceptual uniform space. One could argue +// at length as to what constitutes perceptually uniform, expecially +// when storing either scene/input/focal plane referred and output referred +// data. +// +// We'll compromise. For values <= 1, we use a traditional power function +// (without any of that straight-line business at the bottom). For values > 1, +// we want something more like a log function, since power functions blow +// up. At 1, we want a smooth blend between the functions. So, we use a +// piecewise function that does just that - see dwaLookups.cpp for +// a little more detail. +// +// Also, if we find that we have R, G, and B channels from the same layer, +// we can get a bit more compression efficiency by transforming to a Y'CbCr +// space. We use the 709 transform, but with Cb,Cr = 0 for an input of +// (0, 0, 0), instead of the traditional Cb,Cr = .5. Shifting the zero point +// makes no sense with large range data. Transforms are done to from +// the perceptual space data, not the linear-light space data (R'G'B' -> +// (Y'CbCr, not RGB -> YCbCr). +// +// Next, we forward DCT the data. This is done with a floating +// point DCT, as we don't really have control over the src range. The +// resulting values are dropped to half-float precision. +// +// Now, we need to quantize. Quantization departs from the usual way +// of dividing and rounding. Instead, we start with some floating +// point "base-error" value. From this, we can derive quantization +// error for each DCT component. Take the standard JPEG quantization +// tables and normalize them by the smallest value. Then, multiply +// the normalized quant tables by our base-error value. This gives +// a range of errors for each DCT component. +// +// For each DCT component, we want to find a quantized value that +// is within +- the per-component error. Pick the quantized value +// that has the fewest bits set in its' binary representation. +// Brute-forcing the search would make for extremly inefficient +// compression. Fortunatly, we can precompute a table to assist +// with this search. +// +// For each 16-bit float value, there are at most 15 other values with +// fewer bits set. We can precompute these values in a compact form, since +// many source values have far fewer that 15 possible quantized values. +// Now, instead of searching the entire range +- the component error, +// we can just search at most 15 quantization candidates. The search can +// be accelerated a bit more by sorting the candidates by the +// number of bits set, in increasing order. Then, the search can stop +// once a candidate is found w/i the per-component quantization +// error range. +// +// The quantization strategy has the side-benefit that there is no +// de-quantization step upon decode, so we don't bother recording +// the quantization table. +// +// Ok. So we now have quantized values. Time for entropy coding. We +// can use either static Huffman or zlib/DEFLATE. The static Huffman +// is more efficient at compacting data, but can have a greater +// overhead, especially for smaller tile/strip sizes. +// +// There is some additional fun, like ZIP compressing the DC components +// instead of Huffman/zlib, which helps make things slightly smaller. +// +// Compression level is controlled by setting an int/float/double attribute +// on the header named "dwaCompressionLevel". This is a thinly veiled name for +// the "base-error" value mentioned above. The "base-error" is just +// dwaCompressionLevel / 100000. The default value of 45.0 is generally +// pretty good at generating "visually lossless" values at reasonable +// data rates. Setting dwaCompressionLevel to 0 should result in no additional +// quantization at the quantization stage (though there may be +// quantization in practice at the CSC/DCT steps). But if you really +// want lossless compression, there are pleanty of other choices +// of compressors ;) +// +// When dealing with FLOAT source buffers, we first quantize the source +// to HALF and continue down as we would for HALF source. +// +//--------------------------------------------------- + + +#include "ImfDwaCompressor.h" +#include "ImfDwaCompressorSimd.h" + +#include "ImfChannelList.h" +#include "ImfStandardAttributes.h" +#include "ImfHeader.h" +#include "ImfHuf.h" +#include "ImfInt64.h" +#include "ImfIntAttribute.h" +#include "ImfIO.h" +#include "ImfMisc.h" +#include "ImfNamespace.h" +#include "ImfRle.h" +#include "ImfSimd.h" +#include "ImfSystemSpecific.h" +#include "ImfXdr.h" +#include "ImfZip.h" + +#include "ImathFun.h" +#include "ImathBox.h" +#include "ImathVec.h" +#include "half.h" +#include "halfLimits.h" + +#include "dwaLookups.h" + +#include +#include +#include +#include +#include + +// Windows specific addition to prevent the indirect import of the redefined min/max macros +#if defined _WIN32 || defined _WIN64 + #ifdef NOMINMAX + #undef NOMINMAX + #endif + #define NOMINMAX +#endif +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + + +namespace { + + // + // Function pointer to dispatch to an approprate + // convertFloatToHalf64_* impl, based on runtime cpu checking. + // Should be initialized in DwaCompressor::initializeFuncs() + // + + void (*convertFloatToHalf64)(unsigned short*, float*) = + convertFloatToHalf64_scalar; + + // + // Function pointer for dispatching a fromHalfZigZag_ impl + // + + void (*fromHalfZigZag)(unsigned short*, float*) = + fromHalfZigZag_scalar; + + // + // Dispatch the inverse DCT on an 8x8 block, where the last + // n rows can be all zeros. The n=0 case converts the full block. + // + void (*dctInverse8x8_0)(float*) = dctInverse8x8_scalar<0>; + void (*dctInverse8x8_1)(float*) = dctInverse8x8_scalar<1>; + void (*dctInverse8x8_2)(float*) = dctInverse8x8_scalar<2>; + void (*dctInverse8x8_3)(float*) = dctInverse8x8_scalar<3>; + void (*dctInverse8x8_4)(float*) = dctInverse8x8_scalar<4>; + void (*dctInverse8x8_5)(float*) = dctInverse8x8_scalar<5>; + void (*dctInverse8x8_6)(float*) = dctInverse8x8_scalar<6>; + void (*dctInverse8x8_7)(float*) = dctInverse8x8_scalar<7>; + +} // namespace + + +struct DwaCompressor::ChannelData +{ + std::string name; + CompressorScheme compression; + int xSampling; + int ySampling; + PixelType type; + bool pLinear; + + int width; + int height; + + // + // Incoming and outgoing data is scanline interleaved, and it's much + // easier to operate on contiguous data. Assuming the planare unc + // buffer is to hold RLE data, we need to rearrange to make bytes + // adjacent. + // + + char *planarUncBuffer; + char *planarUncBufferEnd; + + char *planarUncRle[4]; + char *planarUncRleEnd[4]; + + PixelType planarUncType; + int planarUncSize; +}; + + +struct DwaCompressor::CscChannelSet +{ + int idx[3]; +}; + + +struct DwaCompressor::Classifier +{ + Classifier (std::string suffix, + CompressorScheme scheme, + PixelType type, + int cscIdx, + bool caseInsensitive): + _suffix(suffix), + _scheme(scheme), + _type(type), + _cscIdx(cscIdx), + _caseInsensitive(caseInsensitive) + { + if (caseInsensitive) + std::transform(_suffix.begin(), _suffix.end(), _suffix.begin(), tolower); + } + + Classifier (const char *&ptr, int size) + { + if (size <= 0) + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + " (truncated rule)."); + + { + char suffix[Name::SIZE]; + memset (suffix, 0, Name::SIZE); + Xdr::read (ptr, std::min(size, Name::SIZE-1), suffix); + _suffix = std::string(suffix); + } + + if (size < _suffix.length() + 1 + 2*Xdr::size()) + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + " (truncated rule)."); + + char value; + Xdr::read (ptr, value); + + _cscIdx = (int)(value >> 4) - 1; + if (_cscIdx < -1 || _cscIdx >= 3) + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + " (corrupt cscIdx rule)."); + + _scheme = (CompressorScheme)((value >> 2) & 3); + if (_scheme < 0 || _scheme >= NUM_COMPRESSOR_SCHEMES) + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + " (corrupt scheme rule)."); + + _caseInsensitive = (value & 1 ? true : false); + + Xdr::read (ptr, value); + if (value < 0 || value >= NUM_PIXELTYPES) + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + " (corrupt rule)."); + _type = (PixelType)value; + } + + bool match (const std::string &suffix, const PixelType type) const + { + if (_type != type) return false; + + if (_caseInsensitive) + { + std::string tmp(suffix); + std::transform(tmp.begin(), tmp.end(), tmp.begin(), tolower); + return tmp == _suffix; + } + + return suffix == _suffix; + } + + size_t size () const + { + // string length + \0 + size_t sizeBytes = _suffix.length() + 1; + + // 1 byte for scheme / cscIdx / caseInsensitive, and 1 byte for type + sizeBytes += 2 * Xdr::size(); + + return sizeBytes; + } + + void write (char *&ptr) const + { + Xdr::write (ptr, _suffix.c_str()); + + // Encode _cscIdx (-1-3) in the upper 4 bits, + // _scheme (0-2) in the next 2 bits + // _caseInsen in the bottom bit + unsigned char value = 0; + value |= ((unsigned char)(_cscIdx+1) & 15) << 4; + value |= ((unsigned char)_scheme & 3) << 2; + value |= (unsigned char)_caseInsensitive & 1; + + Xdr::write (ptr, value); + Xdr::write (ptr, (unsigned char)_type); + } + + std::string _suffix; + CompressorScheme _scheme; + PixelType _type; + int _cscIdx; + bool _caseInsensitive; +}; + + +// +// Base class for the LOSSY_DCT decoder classes +// + +class DwaCompressor::LossyDctDecoderBase +{ + public: + + LossyDctDecoderBase + (char *packedAc, + char *packedDc, + const unsigned short *toLinear, + int width, + int height); + + virtual ~LossyDctDecoderBase (); + + void execute(); + + // + // These return number of items, not bytes. Each item + // is an unsigned short + // + + int numAcValuesEncoded() const { return _packedAcCount; } + int numDcValuesEncoded() const { return _packedDcCount; } + + protected: + + // + // Un-RLE the packed AC components into + // a half buffer. The half block should + // be the full 8x8 block (in zig-zag order + // still), not the first AC component. + // + // currAcComp is advanced as bytes are decoded. + // + // This returns the index of the last non-zero + // value in the buffer - with the index into zig zag + // order data. If we return 0, we have DC only data. + // + + int unRleAc (unsigned short *&currAcComp, + unsigned short *halfZigBlock); + + + // + // if NATIVE and XDR are really the same values, we can + // skip some processing and speed things along + // + + bool _isNativeXdr; + + + // + // Counts of how many items have been packed into the + // AC and DC buffers + // + + int _packedAcCount; + int _packedDcCount; + + + // + // AC and DC buffers to pack + // + + char *_packedAc; + char *_packedDc; + + + // + // half -> half LUT to transform from nonlinear to linear + // + + const unsigned short *_toLinear; + + + // + // image dimensions + // + + int _width; + int _height; + + + // + // Pointers to the start of each scanlines, to be filled on decode + // Generally, these will be filled by the subclasses. + // + + std::vector< std::vector > _rowPtrs; + + + // + // The type of each data that _rowPtrs[i] is referring. Layout + // is in the same order as _rowPtrs[]. + // + + std::vector _type; + std::vector _dctData; +}; + + +// +// Used to decode a single channel of LOSSY_DCT data. +// + +class DwaCompressor::LossyDctDecoder: public LossyDctDecoderBase +{ + public: + + // + // toLinear is a half-float LUT to convert the encoded values + // back to linear light. If you want to skip this step, pass + // in NULL here. + // + + LossyDctDecoder + (std::vector &rowPtrs, + char *packedAc, + char *packedDc, + const unsigned short *toLinear, + int width, + int height, + PixelType type) + : + LossyDctDecoderBase(packedAc, packedDc, toLinear, width, height) + { + _rowPtrs.push_back(rowPtrs); + _type.push_back(type); + } + + virtual ~LossyDctDecoder () {} +}; + + +// +// Used to decode 3 channels of LOSSY_DCT data that +// are grouped together and color space converted. +// + +class DwaCompressor::LossyDctDecoderCsc: public LossyDctDecoderBase +{ + public: + + // + // toLinear is a half-float LUT to convert the encoded values + // back to linear light. If you want to skip this step, pass + // in NULL here. + // + + LossyDctDecoderCsc + (std::vector &rowPtrsR, + std::vector &rowPtrsG, + std::vector &rowPtrsB, + char *packedAc, + char *packedDc, + const unsigned short *toLinear, + int width, + int height, + PixelType typeR, + PixelType typeG, + PixelType typeB) + : + LossyDctDecoderBase(packedAc, packedDc, toLinear, width, height) + { + _rowPtrs.push_back(rowPtrsR); + _rowPtrs.push_back(rowPtrsG); + _rowPtrs.push_back(rowPtrsB); + _type.push_back(typeR); + _type.push_back(typeG); + _type.push_back(typeB); + } + + virtual ~LossyDctDecoderCsc () {} +}; + + +// +// Base class for encoding using the lossy DCT scheme +// + +class DwaCompressor::LossyDctEncoderBase +{ + public: + + LossyDctEncoderBase + (float quantBaseError, + char *packedAc, + char *packedDc, + const unsigned short *toNonlinear, + int width, + int height); + + virtual ~LossyDctEncoderBase (); + + void execute (); + + // + // These return number of items, not bytes. Each item + // is an unsigned short + // + + int numAcValuesEncoded () const {return _numAcComp;} + int numDcValuesEncoded () const {return _numDcComp;} + + protected: + + void toZigZag (half *dst, half *src); + int countSetBits (unsigned short src); + half quantize (half src, float errorTolerance); + void rleAc (half *block, unsigned short *&acPtr); + + float _quantBaseError; + + int _width, + _height; + const unsigned short *_toNonlinear; + + int _numAcComp, + _numDcComp; + + std::vector< std::vector > _rowPtrs; + std::vector _type; + std::vector _dctData; + + + // + // Pointers to the buffers where AC and DC + // DCT components should be packed for + // lossless compression downstream + // + + char *_packedAc; + char *_packedDc; + + + // + // Our "quantization tables" - the example JPEG tables, + // normalized so that the smallest value in each is 1.0. + // This gives us a relationship between error in DCT + // components + // + + float _quantTableY[64]; + float _quantTableCbCr[64]; +}; + + + +// +// Single channel lossy DCT encoder +// + +class DwaCompressor::LossyDctEncoder: public LossyDctEncoderBase +{ + public: + + LossyDctEncoder + (float quantBaseError, + std::vector &rowPtrs, + char *packedAc, + char *packedDc, + const unsigned short *toNonlinear, + int width, + int height, + PixelType type) + : + LossyDctEncoderBase + (quantBaseError, packedAc, packedDc, toNonlinear, width, height) + { + _rowPtrs.push_back(rowPtrs); + _type.push_back(type); + } + + virtual ~LossyDctEncoder () {} +}; + + +// +// RGB channel lossy DCT encoder +// + +class DwaCompressor::LossyDctEncoderCsc: public LossyDctEncoderBase +{ + public: + + LossyDctEncoderCsc + (float quantBaseError, + std::vector &rowPtrsR, + std::vector &rowPtrsG, + std::vector &rowPtrsB, + char *packedAc, + char *packedDc, + const unsigned short *toNonlinear, + int width, + int height, + PixelType typeR, + PixelType typeG, + PixelType typeB) + : + LossyDctEncoderBase + (quantBaseError, packedAc, packedDc, toNonlinear, width, height) + { + _type.push_back(typeR); + _type.push_back(typeG); + _type.push_back(typeB); + + _rowPtrs.push_back(rowPtrsR); + _rowPtrs.push_back(rowPtrsG); + _rowPtrs.push_back(rowPtrsB); + } + + virtual ~LossyDctEncoderCsc () {} +}; + + +// ============================================================== +// +// LossyDctDecoderBase +// +// -------------------------------------------------------------- + +DwaCompressor::LossyDctDecoderBase::LossyDctDecoderBase + (char *packedAc, + char *packedDc, + const unsigned short *toLinear, + int width, + int height) +: + _isNativeXdr(false), + _packedAcCount(0), + _packedDcCount(0), + _packedAc(packedAc), + _packedDc(packedDc), + _toLinear(toLinear), + _width(width), + _height(height) +{ + if (_toLinear == 0) + _toLinear = get_dwaCompressorNoOp(); + + _isNativeXdr = GLOBAL_SYSTEM_LITTLE_ENDIAN; +} + + +DwaCompressor::LossyDctDecoderBase::~LossyDctDecoderBase () {} + + +void +DwaCompressor::LossyDctDecoderBase::execute () +{ + int numComp = _rowPtrs.size(); + int lastNonZero = 0; + int numBlocksX = (int) ceil ((float)_width / 8.0f); + int numBlocksY = (int) ceil ((float)_height / 8.0f); + int leftoverX = _width - (numBlocksX-1) * 8; + int leftoverY = _height - (numBlocksY-1) * 8; + + int numFullBlocksX = (int)floor ((float)_width / 8.0f); + + unsigned short tmpShortNative = 0; + unsigned short tmpShortXdr = 0; + const char *tmpConstCharPtr = 0; + + unsigned short *currAcComp = (unsigned short *)_packedAc; + std::vector currDcComp (_rowPtrs.size()); + std::vector halfZigBlock (_rowPtrs.size()); + + if (_type.size() != _rowPtrs.size()) + throw IEX_NAMESPACE::BaseExc ("Row pointers and types mismatch in count"); + + if ((_rowPtrs.size() != 3) && (_rowPtrs.size() != 1)) + throw IEX_NAMESPACE::NoImplExc ("Only 1 and 3 channel encoding is supported"); + + _dctData.resize(numComp); + + // + // Allocate a temp aligned buffer to hold a rows worth of full + // 8x8 half-float blocks + // + + unsigned char *rowBlockHandle = new unsigned char + [numComp * numBlocksX * 64 * sizeof(unsigned short) + _SSE_ALIGNMENT]; + + unsigned short *rowBlock[3]; + + rowBlock[0] = (unsigned short*)rowBlockHandle; + + for (int i = 0; i < _SSE_ALIGNMENT; ++i) + { + if (((size_t)(rowBlockHandle + i) & _SSE_ALIGNMENT_MASK) == 0) + rowBlock[0] = (unsigned short *)(rowBlockHandle + i); + } + + for (int comp = 1; comp < numComp; ++comp) + rowBlock[comp] = rowBlock[comp - 1] + numBlocksX * 64; + + // + // Pack DC components together by common plane, so we can get + // a little more out of differencing them. We'll always have + // one component per block, so we can computed offsets. + // + + currDcComp[0] = (unsigned short *)_packedDc; + + for (unsigned int comp = 1; comp < numComp; ++comp) + currDcComp[comp] = currDcComp[comp - 1] + numBlocksX * numBlocksY; + + for (int blocky = 0; blocky < numBlocksY; ++blocky) + { + int maxY = 8; + + if (blocky == numBlocksY-1) + maxY = leftoverY; + + int maxX = 8; + + for (int blockx = 0; blockx < numBlocksX; ++blockx) + { + if (blockx == numBlocksX-1) + maxX = leftoverX; + + // + // If we can detect that the block is constant values + // (all components only have DC values, and all AC is 0), + // we can do everything only on 1 value, instead of all + // 64. + // + // This won't really help for regular images, but it is + // meant more for layers with large swaths of black + // + + bool blockIsConstant = true; + + for (unsigned int comp = 0; comp < numComp; ++comp) + { + + // + // DC component is stored separately + // + + #ifdef IMF_HAVE_SSE2 + { + __m128i *dst = (__m128i*)halfZigBlock[comp]._buffer; + + dst[7] = _mm_setzero_si128(); + dst[6] = _mm_setzero_si128(); + dst[5] = _mm_setzero_si128(); + dst[4] = _mm_setzero_si128(); + dst[3] = _mm_setzero_si128(); + dst[2] = _mm_setzero_si128(); + dst[1] = _mm_setzero_si128(); + dst[0] = _mm_insert_epi16 + (_mm_setzero_si128(), *currDcComp[comp]++, 0); + } + #else /* IMF_HAVE_SSE2 */ + + memset (halfZigBlock[comp]._buffer, 0, 64 * 2); + halfZigBlock[comp]._buffer[0] = *currDcComp[comp]++; + + #endif /* IMF_HAVE_SSE2 */ + + _packedDcCount++; + + // + // UnRLE the AC. This will modify currAcComp + // + + lastNonZero = unRleAc (currAcComp, halfZigBlock[comp]._buffer); + + // + // Convert from XDR to NATIVE + // + + if (!_isNativeXdr) + { + for (int i = 0; i < 64; ++i) + { + tmpShortXdr = halfZigBlock[comp]._buffer[i]; + tmpConstCharPtr = (const char *)&tmpShortXdr; + + Xdr::read (tmpConstCharPtr, tmpShortNative); + + halfZigBlock[comp]._buffer[i] = tmpShortNative; + } + } + + if (lastNonZero == 0) + { + // + // DC only case - AC components are all 0 + // + + half h; + + h.setBits (halfZigBlock[comp]._buffer[0]); + _dctData[comp]._buffer[0] = (float)h; + + dctInverse8x8DcOnly (_dctData[comp]._buffer); + } + else + { + // + // We have some AC components that are non-zero. + // Can't use the 'constant block' optimization + // + + blockIsConstant = false; + + // + // Un-Zig zag + // + + (*fromHalfZigZag) + (halfZigBlock[comp]._buffer, _dctData[comp]._buffer); + + // + // Zig-Zag indices in normal layout are as follows: + // + // 0 1 5 6 14 15 27 28 + // 2 4 7 13 16 26 29 42 + // 3 8 12 17 25 30 41 43 + // 9 11 18 24 31 40 44 53 + // 10 19 23 32 39 45 52 54 + // 20 22 33 38 46 51 55 60 + // 21 34 37 47 50 56 59 61 + // 35 36 48 49 57 58 62 63 + // + // If lastNonZero is less than the first item on + // each row, we know that the whole row is zero and + // can be skipped in the row-oriented part of the + // iDCT. + // + // The unrolled logic here is: + // + // if lastNonZero < rowStartIdx[i], + // zeroedRows = rowsEmpty[i] + // + // where: + // + // const int rowStartIdx[] = {2, 3, 9, 10, 20, 21, 35}; + // const int rowsEmpty[] = {7, 6, 5, 4, 3, 2, 1}; + // + + if (lastNonZero < 2) + dctInverse8x8_7(_dctData[comp]._buffer); + else if (lastNonZero < 3) + dctInverse8x8_6(_dctData[comp]._buffer); + else if (lastNonZero < 9) + dctInverse8x8_5(_dctData[comp]._buffer); + else if (lastNonZero < 10) + dctInverse8x8_4(_dctData[comp]._buffer); + else if (lastNonZero < 20) + dctInverse8x8_3(_dctData[comp]._buffer); + else if (lastNonZero < 21) + dctInverse8x8_2(_dctData[comp]._buffer); + else if (lastNonZero < 35) + dctInverse8x8_1(_dctData[comp]._buffer); + else + dctInverse8x8_0(_dctData[comp]._buffer); + } + } + + // + // Perform the CSC + // + + if (numComp == 3) + { + if (!blockIsConstant) + { + csc709Inverse64 (_dctData[0]._buffer, + _dctData[1]._buffer, + _dctData[2]._buffer); + + } + else + { + csc709Inverse (_dctData[0]._buffer[0], + _dctData[1]._buffer[0], + _dctData[2]._buffer[0]); + } + } + + // + // Float -> Half conversion. + // + // If the block has a constant value, just convert the first pixel. + // + + for (unsigned int comp = 0; comp < numComp; ++comp) + { + if (!blockIsConstant) + { + (*convertFloatToHalf64) + (&rowBlock[comp][blockx*64], _dctData[comp]._buffer); + } + else + { + #ifdef IMF_HAVE_SSE2 + + __m128i *dst = (__m128i*)&rowBlock[comp][blockx*64]; + + dst[0] = _mm_set1_epi16 + (((half)_dctData[comp]._buffer[0]).bits()); + + dst[1] = dst[0]; + dst[2] = dst[0]; + dst[3] = dst[0]; + dst[4] = dst[0]; + dst[5] = dst[0]; + dst[6] = dst[0]; + dst[7] = dst[0]; + + #else /* IMF_HAVE_SSE2 */ + + unsigned short *dst = &rowBlock[comp][blockx*64]; + + dst[0] = ((half)_dctData[comp]._buffer[0]).bits(); + + for (int i = 1; i < 64; ++i) + { + dst[i] = dst[0]; + } + + #endif /* IMF_HAVE_SSE2 */ + } // blockIsConstant + } // comp + } // blockx + + // + // At this point, we have half-float nonlinear value blocked + // in rowBlock[][]. We need to unblock the data, transfer + // back to linear, and write the results in the _rowPtrs[]. + // + // There is a fast-path for aligned rows, which helps + // things a little. Since this fast path is only valid + // for full 8-element wide blocks, the partial x blocks + // are broken into a separate loop below. + // + // At the moment, the fast path requires: + // * sse support + // * aligned row pointers + // * full 8-element wide blocks + // + + for (int comp = 0; comp < numComp; ++comp) + { + // + // Test if we can use the fast path + // + + #ifdef IMF_HAVE_SSE2 + + bool fastPath = true; + + for (int y = 8 * blocky; y < 8 * blocky + maxY; ++y) + { + if ((size_t)_rowPtrs[comp][y] & _SSE_ALIGNMENT_MASK) + fastPath = false; + } + + if (fastPath) + { + // + // Handle all the full X blocks, in a fast path with sse2 and + // aligned row pointers + // + + for (int y=8*blocky; y<8*blocky+maxY; ++y) + { + __m128i *dst = (__m128i *)_rowPtrs[comp][y]; + __m128i *src = (__m128i *)&rowBlock[comp][(y & 0x7) * 8]; + + + for (int blockx = 0; blockx < numFullBlocksX; ++blockx) + { + // + // These may need some twiddling. + // Run with multiples of 8 + // + + _mm_prefetch ((char *)(src + 16), _MM_HINT_NTA); + + unsigned short i0 = _mm_extract_epi16 (*src, 0); + unsigned short i1 = _mm_extract_epi16 (*src, 1); + unsigned short i2 = _mm_extract_epi16 (*src, 2); + unsigned short i3 = _mm_extract_epi16 (*src, 3); + + unsigned short i4 = _mm_extract_epi16 (*src, 4); + unsigned short i5 = _mm_extract_epi16 (*src, 5); + unsigned short i6 = _mm_extract_epi16 (*src, 6); + unsigned short i7 = _mm_extract_epi16 (*src, 7); + + i0 = _toLinear[i0]; + i1 = _toLinear[i1]; + i2 = _toLinear[i2]; + i3 = _toLinear[i3]; + + i4 = _toLinear[i4]; + i5 = _toLinear[i5]; + i6 = _toLinear[i6]; + i7 = _toLinear[i7]; + + *dst = _mm_insert_epi16 (_mm_setzero_si128(), i0, 0); + *dst = _mm_insert_epi16 (*dst, i1, 1); + *dst = _mm_insert_epi16 (*dst, i2, 2); + *dst = _mm_insert_epi16 (*dst, i3, 3); + + *dst = _mm_insert_epi16 (*dst, i4, 4); + *dst = _mm_insert_epi16 (*dst, i5, 5); + *dst = _mm_insert_epi16 (*dst, i6, 6); + *dst = _mm_insert_epi16 (*dst, i7, 7); + + src += 8; + dst++; + } + } + } + else + { + + #endif /* IMF_HAVE_SSE2 */ + + // + // Basic scalar kinda slow path for handling the full X blocks + // + + for (int y = 8 * blocky; y < 8 * blocky + maxY; ++y) + { + unsigned short *dst = (unsigned short *)_rowPtrs[comp][y]; + + for (int blockx = 0; blockx < numFullBlocksX; ++blockx) + { + unsigned short *src = + &rowBlock[comp][blockx * 64 + ((y & 0x7) * 8)]; + + dst[0] = _toLinear[src[0]]; + dst[1] = _toLinear[src[1]]; + dst[2] = _toLinear[src[2]]; + dst[3] = _toLinear[src[3]]; + + dst[4] = _toLinear[src[4]]; + dst[5] = _toLinear[src[5]]; + dst[6] = _toLinear[src[6]]; + dst[7] = _toLinear[src[7]]; + + dst += 8; + } + } + + #ifdef IMF_HAVE_SSE2 + + } + + #endif /* IMF_HAVE_SSE2 */ + + // + // If we have partial X blocks, deal with all those now + // Since this should be minimal work, there currently + // is only one path that should work for everyone. + // + + if (numFullBlocksX != numBlocksX) + { + for (int y = 8 * blocky; y < 8 * blocky + maxY; ++y) + { + unsigned short *src = (unsigned short *) + &rowBlock[comp][numFullBlocksX * 64 + ((y & 0x7) * 8)]; + + unsigned short *dst = (unsigned short *)_rowPtrs[comp][y]; + + dst += 8 * numFullBlocksX; + + for (int x = 0; x < maxX; ++x) + { + *dst++ = _toLinear[*src++]; + } + } + } + } // comp + } // blocky + + // + // Walk over all the channels that are of type FLOAT. + // Convert from HALF XDR back to FLOAT XDR. + // + + for (unsigned int chan = 0; chan < numComp; ++chan) + { + + if (_type[chan] != FLOAT) + continue; + + std::vector halfXdr (_width); + + for (int y=0; y<_height; ++y) + { + char *floatXdrPtr = _rowPtrs[chan][y]; + + memcpy(&halfXdr[0], floatXdrPtr, _width*sizeof(unsigned short)); + + const char *halfXdrPtr = (const char *)(&halfXdr[0]); + + for (int x=0; x<_width; ++x) + { + half tmpHalf; + + Xdr::read (halfXdrPtr, tmpHalf); + Xdr::write (floatXdrPtr, (float)tmpHalf); + + // + // Xdr::write and Xdr::read will advance the ptrs + // + } + } + } + + delete[] rowBlockHandle; +} + + +// +// Un-RLE the packed AC components into +// a half buffer. The half block should +// be the full 8x8 block (in zig-zag order +// still), not the first AC component. +// +// currAcComp is advanced as bytes are decoded. +// +// This returns the index of the last non-zero +// value in the buffer - with the index into zig zag +// order data. If we return 0, we have DC only data. +// +// This is assuminging that halfZigBlock is zero'ed +// prior to calling +// + +int +DwaCompressor::LossyDctDecoderBase::unRleAc + (unsigned short *&currAcComp, + unsigned short *halfZigBlock) +{ + // + // Un-RLE the RLE'd blocks. If we find an item whose + // high byte is 0xff, then insert the number of 0's + // as indicated by the low byte. + // + // Otherwise, just copy the number verbaitm. + // + + int lastNonZero = 0; + int dctComp = 1; + + // + // Start with a zero'ed block, so we don't have to + // write when we hit a run symbol + // + + while (dctComp < 64) + { + if (*currAcComp == 0xff00) + { + // + // End of block + // + + dctComp = 64; + + } + else if ((*currAcComp) >> 8 == 0xff) + { + // + // Run detected! Insert 0's. + // + // Since the block has been zeroed, just advance the ptr + // + + dctComp += (*currAcComp) & 0xff; + } + else + { + // + // Not a run, just copy over the value + // + + lastNonZero = dctComp; + halfZigBlock[dctComp] = *currAcComp; + + dctComp++; + } + + _packedAcCount++; + currAcComp++; + } + + return lastNonZero; +} + + +// ============================================================== +// +// LossyDctEncoderBase +// +// -------------------------------------------------------------- + +DwaCompressor::LossyDctEncoderBase::LossyDctEncoderBase + (float quantBaseError, + char *packedAc, + char *packedDc, + const unsigned short *toNonlinear, + int width, + int height) +: + _quantBaseError(quantBaseError), + _width(width), + _height(height), + _toNonlinear(toNonlinear), + _numAcComp(0), + _numDcComp(0), + _packedAc(packedAc), + _packedDc(packedDc) +{ + // + // Here, we take the generic JPEG quantization tables and + // normalize them by the smallest component in each table. + // This gives us a relationship amongst the DCT components, + // in terms of how sensitive each component is to + // error. + // + // A higher normalized value means we can quantize more, + // and a small normalized value means we can quantize less. + // + // Eventually, we will want an acceptable quantization + // error range for each component. We find this by + // multiplying some user-specified level (_quantBaseError) + // by the normalized table (_quantTableY, _quantTableCbCr) to + // find the acceptable quantization error range. + // + // The quantization table is not needed for decoding, and + // is not transmitted. So, if you want to get really fancy, + // you could derive some content-dependent quantization + // table, and the decoder would not need to be changed. But, + // for now, we'll just use statice quantization tables. + // + + int jpegQuantTableY[] = + { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 + }; + + int jpegQuantTableYMin = 10; + + int jpegQuantTableCbCr[] = + { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 + }; + + int jpegQuantTableCbCrMin = 17; + + for (int idx = 0; idx < 64; ++idx) + { + _quantTableY[idx] = static_cast (jpegQuantTableY[idx]) / + static_cast (jpegQuantTableYMin); + + _quantTableCbCr[idx] = static_cast (jpegQuantTableCbCr[idx]) / + static_cast (jpegQuantTableCbCrMin); + } + + if (_quantBaseError < 0) + quantBaseError = 0; +} + + +DwaCompressor::LossyDctEncoderBase::~LossyDctEncoderBase () +{ +} + + +// +// Given three channels of source data, encoding by first applying +// a color space conversion to a YCbCr space. Otherwise, if we only +// have one channel, just encode it as is. +// +// Other numbers of channels are somewhat unexpected at this point, +// and will throw an exception. +// + +void +DwaCompressor::LossyDctEncoderBase::execute () +{ + int numBlocksX = (int)ceil ((float)_width / 8.0f); + int numBlocksY = (int)ceil ((float)_height/ 8.0f); + + half halfZigCoef[64]; + half halfCoef[64]; + + std::vector currDcComp (_rowPtrs.size()); + unsigned short *currAcComp = (unsigned short *)_packedAc; + + _dctData.resize (_rowPtrs.size()); + _numAcComp = 0; + _numDcComp = 0; + + assert (_type.size() == _rowPtrs.size()); + assert ((_rowPtrs.size() == 3) || (_rowPtrs.size() == 1)); + + // + // Allocate a temp half buffer to quantize into for + // any FLOAT source channels. + // + + int tmpHalfBufferElements = 0; + + for (unsigned int chan = 0; chan < _rowPtrs.size(); ++chan) + if (_type[chan] == FLOAT) + tmpHalfBufferElements += _width * _height; + + std::vector tmpHalfBuffer (tmpHalfBufferElements); + + char *tmpHalfBufferPtr = 0; + + if (tmpHalfBufferElements) + tmpHalfBufferPtr = (char *)&tmpHalfBuffer[0]; + + // + // Run over all the float scanlines, quantizing, + // and re-assigning _rowPtr[y]. We need to translate + // FLOAT XDR to HALF XDR. + // + + for (unsigned int chan = 0; chan < _rowPtrs.size(); ++chan) + { + if (_type[chan] != FLOAT) + continue; + + for (int y = 0; y < _height; ++y) + { + float src = 0; + const char *srcXdr = _rowPtrs[chan][y]; + char *dstXdr = tmpHalfBufferPtr; + + for (int x = 0; x < _width; ++x) + { + + Xdr::read (srcXdr, src); + + // + // Clamp to half ranges, instead of just casting. This + // avoids introducing Infs which end up getting zeroed later + // + src = std::max ( + std::min ((float) std::numeric_limits::max(), src), + (float)-std::numeric_limits::max()); + + Xdr::write (dstXdr, ((half)src).bits()); + + // + // Xdr::read and Xdr::write will advance the ptr + // + } + + _rowPtrs[chan][y] = (const char *)tmpHalfBufferPtr; + tmpHalfBufferPtr += _width * sizeof (unsigned short); + } + } + + // + // Pack DC components together by common plane, so we can get + // a little more out of differencing them. We'll always have + // one component per block, so we can computed offsets. + // + + currDcComp[0] = (unsigned short *)_packedDc; + + for (unsigned int chan = 1; chan < _rowPtrs.size(); ++chan) + currDcComp[chan] = currDcComp[chan-1] + numBlocksX * numBlocksY; + + for (int blocky = 0; blocky < numBlocksY; ++blocky) + { + for (int blockx = 0; blockx < numBlocksX; ++blockx) + { + half h; + unsigned short tmpShortXdr, tmpShortNative; + char *tmpCharPtr; + + for (unsigned int chan = 0; chan < _rowPtrs.size(); ++chan) + { + // + // Break the source into 8x8 blocks. If we don't + // fit at the edges, mirror. + // + // Also, convert from linear to nonlinear representation. + // Our source is assumed to be XDR, and we need to convert + // to NATIVE prior to converting to float. + // + // If we're converting linear -> nonlinear, assume that the + // XDR -> NATIVE conversion is built into the lookup. Otherwise, + // we'll need to explicitly do it. + // + + for (int y = 0; y < 8; ++y) + { + for (int x = 0; x < 8; ++x) + { + int vx = 8 * blockx + x; + int vy = 8 * blocky + y; + + if (vx >= _width) + vx = _width - (vx - (_width - 1)); + + if (vx < 0) vx = _width-1; + + if (vy >=_height) + vy = _height - (vy - (_height - 1)); + + if (vy < 0) vy = _height-1; + + tmpShortXdr = + ((const unsigned short *)(_rowPtrs[chan])[vy])[vx]; + + if (_toNonlinear) + { + h.setBits (_toNonlinear[tmpShortXdr]); + } + else + { + const char *tmpConstCharPtr = + (const char *)(&tmpShortXdr); + + Xdr::read + (tmpConstCharPtr, tmpShortNative); + + h.setBits(tmpShortNative); + } + + _dctData[chan]._buffer[y * 8 + x] = (float)h; + } // x + } // y + } // chan + + // + // Color space conversion + // + + if (_rowPtrs.size() == 3) + { + csc709Forward64 (_dctData[0]._buffer, + _dctData[1]._buffer, + _dctData[2]._buffer); + } + + for (unsigned int chan = 0; chan < _rowPtrs.size(); ++chan) + { + // + // Forward DCT + // + + dctForward8x8(_dctData[chan]._buffer); + + // + // Quantize to half, and zigzag + // + + if (chan == 0) + { + for (int i = 0; i < 64; ++i) + { + halfCoef[i] = + quantize ((half)_dctData[chan]._buffer[i], + _quantBaseError*_quantTableY[i]); + } + } + else + { + for (int i = 0; i < 64; ++i) + { + halfCoef[i] = + quantize ((half)_dctData[chan]._buffer[i], + _quantBaseError*_quantTableCbCr[i]); + } + } + + toZigZag (halfZigCoef, halfCoef); + + // + // Convert from NATIVE back to XDR, before we write out + // + + for (int i = 0; i < 64; ++i) + { + tmpCharPtr = (char *)&tmpShortXdr; + Xdr::write(tmpCharPtr, halfZigCoef[i].bits()); + halfZigCoef[i].setBits(tmpShortXdr); + } + + // + // Save the DC component separately, to be compressed on + // its own. + // + + *currDcComp[chan]++ = halfZigCoef[0].bits(); + _numDcComp++; + + // + // Then RLE the AC components (which will record the count + // of the resulting number of items) + // + + rleAc (halfZigCoef, currAcComp); + } // chan + } // blockx + } // blocky +} + + +// +// Reorder from zig-zag order to normal ordering +// + +void +DwaCompressor::LossyDctEncoderBase::toZigZag (half *dst, half *src) +{ + const int remap[] = + { + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 + }; + + for (int i=0; i<64; ++i) + dst[i] = src[remap[i]]; +} + + +// +// Precomputing the bit count runs faster than using +// the builtin instruction, at least in one case.. +// +// Precomputing 8-bits is no slower than 16-bits, +// and saves a fair bit of overhead.. +// + +int +DwaCompressor::LossyDctEncoderBase::countSetBits (unsigned short src) +{ + static const unsigned short numBitsSet[256] = + { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 + }; + + return numBitsSet[src & 0xff] + numBitsSet[src >> 8]; +} + + +// +// Take a DCT coefficient, as well as an acceptable error. Search +// nearby values within the error tolerance, that have fewer +// bits set. +// +// The list of candidates has been pre-computed and sorted +// in order of increasing numbers of bits set. This way, we +// can stop searching as soon as we find a candidate that +// is within the error tolerance. +// + +half +DwaCompressor::LossyDctEncoderBase::quantize (half src, float errorTolerance) +{ + half tmp; + float srcFloat = (float)src; + int numSetBits = countSetBits(src.bits()); + const unsigned short *closest = get_dwaClosest(src.bits()); + + for (int targetNumSetBits = numSetBits - 1; + targetNumSetBits >= 0; + --targetNumSetBits) + { + tmp.setBits (*closest); + + if (fabs ((float)tmp - srcFloat) < errorTolerance) + return tmp; + + closest++; + } + + return src; +} + + +// +// RLE the zig-zag of the AC components + copy over +// into another tmp buffer +// +// Try to do a simple RLE scheme to reduce run's of 0's. This +// differs from the jpeg EOB case, since EOB just indicates that +// the rest of the block is zero. In our case, we have lots of +// NaN symbols, which shouldn't be allowed to occur in DCT +// coefficents - so we'll use them for encoding runs. +// +// If the high byte is 0xff, then we have a run of 0's, of length +// given by the low byte. For example, 0xff03 would be a run +// of 3 0's, starting at the current location. +// +// block is our block of 64 coefficients +// acPtr a pointer to back the RLE'd values into. +// +// This will advance the counter, _numAcComp. +// + +void +DwaCompressor::LossyDctEncoderBase::rleAc + (half *block, + unsigned short *&acPtr) +{ + int dctComp = 1; + unsigned short rleSymbol = 0x0; + + while (dctComp < 64) + { + int runLen = 1; + + // + // If we don't have a 0, output verbatim + // + + if (block[dctComp].bits() != rleSymbol) + { + *acPtr++ = block[dctComp].bits(); + _numAcComp++; + + dctComp += runLen; + continue; + } + + // + // We're sitting on a 0, so see how big the run is. + // + + while ((dctComp+runLen < 64) && + (block[dctComp+runLen].bits() == rleSymbol)) + { + runLen++; + } + + // + // If the run len is too small, just output verbatim + // otherwise output our run token + // + // Originally, we wouldn't have a separate symbol for + // "end of block". But in some experimentation, it looks + // like using 0xff00 for "end of block" can save a bit + // of space. + // + + if (runLen == 1) + { + runLen = 1; + *acPtr++ = block[dctComp].bits(); + _numAcComp++; + + // + // Using 0xff00 for "end of block" + // + } + else if (runLen + dctComp == 64) + { + // + // Signal EOB + // + + *acPtr++ = 0xff00; + _numAcComp++; + } + else + { + // + // Signal normal run + // + + *acPtr++ = 0xff00 | runLen; + _numAcComp++; + } + + // + // Advance by runLen + // + + dctComp += runLen; + } +} + + +// ============================================================== +// +// DwaCompressor +// +// -------------------------------------------------------------- + +// +// DwaCompressor() +// + +DwaCompressor::DwaCompressor + (const Header &hdr, + int maxScanLineSize, + int numScanLines, + AcCompression acCompression) +: + Compressor(hdr), + _acCompression(acCompression), + _maxScanLineSize(maxScanLineSize), + _numScanLines(numScanLines), + _channels(hdr.channels()), + _packedAcBuffer(0), + _packedAcBufferSize(0), + _packedDcBuffer(0), + _packedDcBufferSize(0), + _rleBuffer(0), + _rleBufferSize(0), + _outBuffer(0), + _outBufferSize(0), + _zip(0), + _dwaCompressionLevel(45.0) +{ + _min[0] = hdr.dataWindow().min.x; + _min[1] = hdr.dataWindow().min.y; + _max[0] = hdr.dataWindow().max.x; + _max[1] = hdr.dataWindow().max.y; + + for (int i=0; i < NUM_COMPRESSOR_SCHEMES; ++i) + { + _planarUncBuffer[i] = 0; + _planarUncBufferSize[i] = 0; + } + + // + // Check the header for a quality attribute + // + + if (hasDwaCompressionLevel (hdr)) + _dwaCompressionLevel = dwaCompressionLevel (hdr); +} + + +DwaCompressor::~DwaCompressor() +{ + delete[] _packedAcBuffer; + delete[] _packedDcBuffer; + delete[] _rleBuffer; + delete[] _outBuffer; + delete _zip; + + for (int i=0; i channelRules; + if (fileVersion >= 2) + { + relevantChannelRules(channelRules); + + channelRuleSize = Xdr::size(); + for (size_t i = 0; i < channelRules.size(); ++i) + channelRuleSize += channelRules[i].size(); + } + + // + // Remember to allocate _outBuffer, if we haven't done so already. + // + + outBufferSize += channelRuleSize; + if (outBufferSize > _outBufferSize) + { + _outBufferSize = outBufferSize; + if (_outBuffer != 0) + delete[] _outBuffer; + _outBuffer = new char[outBufferSize]; + } + + char *outDataPtr = &_outBuffer[NUM_SIZES_SINGLE * sizeof(OPENEXR_IMF_NAMESPACE::Int64) + + channelRuleSize]; + + // + // We might not be dealing with any color data, in which + // case the AC buffer size will be 0, and deferencing + // a vector will not be a good thing to do. + // + + if (_packedAcBuffer) + packedAcEnd = _packedAcBuffer; + + if (_packedDcBuffer) + packedDcEnd = _packedDcBuffer; + + #define OBIDX(x) (Int64 *)&_outBuffer[x * sizeof (Int64)] + + Int64 *version = OBIDX (VERSION); + Int64 *unknownUncompressedSize = OBIDX (UNKNOWN_UNCOMPRESSED_SIZE); + Int64 *unknownCompressedSize = OBIDX (UNKNOWN_COMPRESSED_SIZE); + Int64 *acCompressedSize = OBIDX (AC_COMPRESSED_SIZE); + Int64 *dcCompressedSize = OBIDX (DC_COMPRESSED_SIZE); + Int64 *rleCompressedSize = OBIDX (RLE_COMPRESSED_SIZE); + Int64 *rleUncompressedSize = OBIDX (RLE_UNCOMPRESSED_SIZE); + Int64 *rleRawSize = OBIDX (RLE_RAW_SIZE); + + Int64 *totalAcUncompressedCount = OBIDX (AC_UNCOMPRESSED_COUNT); + Int64 *totalDcUncompressedCount = OBIDX (DC_UNCOMPRESSED_COUNT); + + Int64 *acCompression = OBIDX (AC_COMPRESSION); + + int minX = range.min.x; + int maxX = std::min(range.max.x, _max[0]); + int minY = range.min.y; + int maxY = std::min(range.max.y, _max[1]); + + // + // Zero all the numbers in the chunk header + // + + memset (_outBuffer, 0, NUM_SIZES_SINGLE * sizeof (Int64)); + + // + // Setup the AC compression strategy and the version in the data block, + // then write the relevant channel classification rules if needed + // + *version = fileVersion; + *acCompression = _acCompression; + + setupChannelData (minX, minY, maxX, maxY); + + if (fileVersion >= 2) + { + char *writePtr = &_outBuffer[NUM_SIZES_SINGLE * sizeof(OPENEXR_IMF_NAMESPACE::Int64)]; + Xdr::write (writePtr, channelRuleSize); + + for (size_t i = 0; i < channelRules.size(); ++i) + channelRules[i].write(writePtr); + } + + // + // Determine the start of each row in the input buffer + // Channels are interleaved by scanline + // + + std::vector encodedChannels (_channelData.size()); + std::vector< std::vector > rowPtrs (_channelData.size()); + + for (unsigned int chan = 0; chan < _channelData.size(); ++chan) + encodedChannels[chan] = false; + + inDataPtr = inPtr; + + for (int y = minY; y <= maxY; ++y) + { + for (unsigned int chan = 0; chan < _channelData.size(); ++chan) + { + + ChannelData *cd = &_channelData[chan]; + + if (IMATH_NAMESPACE::modp(y, cd->ySampling) != 0) + continue; + + rowPtrs[chan].push_back(inDataPtr); + inDataPtr += cd->width * OPENEXR_IMF_NAMESPACE::pixelTypeSize(cd->type); + } + } + + inDataPtr = inPtr; + + // + // Make a pass over all our CSC sets and try to encode them first + // + + for (unsigned int csc = 0; csc < _cscSets.size(); ++csc) + { + + LossyDctEncoderCsc encoder + (_dwaCompressionLevel / 100000.f, + rowPtrs[_cscSets[csc].idx[0]], + rowPtrs[_cscSets[csc].idx[1]], + rowPtrs[_cscSets[csc].idx[2]], + packedAcEnd, + packedDcEnd, + get_dwaCompressorToNonlinear(), + _channelData[_cscSets[csc].idx[0]].width, + _channelData[_cscSets[csc].idx[0]].height, + _channelData[_cscSets[csc].idx[0]].type, + _channelData[_cscSets[csc].idx[1]].type, + _channelData[_cscSets[csc].idx[2]].type); + + encoder.execute(); + + *totalAcUncompressedCount += encoder.numAcValuesEncoded(); + *totalDcUncompressedCount += encoder.numDcValuesEncoded(); + + packedAcEnd += encoder.numAcValuesEncoded() * sizeof(unsigned short); + packedDcEnd += encoder.numDcValuesEncoded() * sizeof(unsigned short); + + encodedChannels[_cscSets[csc].idx[0]] = true; + encodedChannels[_cscSets[csc].idx[1]] = true; + encodedChannels[_cscSets[csc].idx[2]] = true; + } + + for (unsigned int chan = 0; chan < _channelData.size(); ++chan) + { + ChannelData *cd = &_channelData[chan]; + + if (encodedChannels[chan]) + continue; + + switch (cd->compression) + { + case LOSSY_DCT: + + // + // For LOSSY_DCT, treat this just like the CSC'd case, + // but only operate on one channel + // + + { + const unsigned short *nonlinearLut = 0; + + if (!cd->pLinear) + nonlinearLut = get_dwaCompressorToNonlinear(); + + LossyDctEncoder encoder + (_dwaCompressionLevel / 100000.f, + rowPtrs[chan], + packedAcEnd, + packedDcEnd, + nonlinearLut, + cd->width, + cd->height, + cd->type); + + encoder.execute(); + + *totalAcUncompressedCount += encoder.numAcValuesEncoded(); + *totalDcUncompressedCount += encoder.numDcValuesEncoded(); + + packedAcEnd += + encoder.numAcValuesEncoded() * sizeof (unsigned short); + + packedDcEnd += + encoder.numDcValuesEncoded() * sizeof (unsigned short); + } + + break; + + case RLE: + + // + // For RLE, bash the bytes up so that the first bytes of each + // pixel are contingous, as are the second bytes, and so on. + // + + for (unsigned int y = 0; y < rowPtrs[chan].size(); ++y) + { + const char *row = rowPtrs[chan][y]; + + for (int x = 0; x < cd->width; ++x) + { + for (int byte = 0; + byte < OPENEXR_IMF_NAMESPACE::pixelTypeSize (cd->type); + ++byte) + { + + *cd->planarUncRleEnd[byte]++ = *row++; + } + } + + *rleRawSize += cd->width * OPENEXR_IMF_NAMESPACE::pixelTypeSize(cd->type); + } + + break; + + case UNKNOWN: + + // + // Otherwise, just copy data over verbatim + // + + { + int scanlineSize = cd->width * OPENEXR_IMF_NAMESPACE::pixelTypeSize(cd->type); + + for (unsigned int y = 0; y < rowPtrs[chan].size(); ++y) + { + memcpy (cd->planarUncBufferEnd, + rowPtrs[chan][y], + scanlineSize); + + cd->planarUncBufferEnd += scanlineSize; + } + + *unknownUncompressedSize += cd->planarUncSize; + } + + break; + + default: + + assert (false); + } + + encodedChannels[chan] = true; + } + + // + // Pack the Unknown data into the output buffer first. Instead of + // just copying it uncompressed, try zlib compression at least. + // + + if (*unknownUncompressedSize > 0) + { + uLongf inSize = (uLongf)(*unknownUncompressedSize); + uLongf outSize = compressBound (inSize); + + if (Z_OK != ::compress2 ((Bytef *)outDataPtr, + &outSize, + (const Bytef *)_planarUncBuffer[UNKNOWN], + inSize, + 9)) + { + throw IEX_NAMESPACE::BaseExc ("Data compression (zlib) failed."); + } + + outDataPtr += outSize; + *unknownCompressedSize = outSize; + } + + // + // Now, pack all the Lossy DCT coefficients into our output + // buffer, with Huffman encoding. + // + // Also, record the compressed size and the number of + // uncompressed componentns we have. + // + + if (*totalAcUncompressedCount > 0) + { + switch (_acCompression) + { + case STATIC_HUFFMAN: + + *acCompressedSize = (int) + hufCompress((unsigned short *)_packedAcBuffer, + (int)*totalAcUncompressedCount, + outDataPtr); + break; + + case DEFLATE: + + { + uLongf destLen = compressBound ( + (*totalAcUncompressedCount) * sizeof (unsigned short)); + + if (Z_OK != ::compress2 + ((Bytef *)outDataPtr, + &destLen, + (Bytef *)_packedAcBuffer, + (uLong)(*totalAcUncompressedCount + * sizeof (unsigned short)), + 9)) + { + throw IEX_NAMESPACE::InputExc ("Data compression (zlib) failed."); + } + + *acCompressedSize = destLen; + } + + break; + + default: + + assert (false); + } + + outDataPtr += *acCompressedSize; + } + + // + // Handle the DC components separately + // + + if (*totalDcUncompressedCount > 0) + { + *dcCompressedSize = _zip->compress + (_packedDcBuffer, + (int)(*totalDcUncompressedCount) * sizeof (unsigned short), + outDataPtr); + + outDataPtr += *dcCompressedSize; + } + + // + // If we have RLE data, first RLE encode it and set the uncompressed + // size. Then, deflate the results and set the compressed size. + // + + if (*rleRawSize > 0) + { + *rleUncompressedSize = rleCompress + ((int)(*rleRawSize), + _planarUncBuffer[RLE], + (signed char *)_rleBuffer); + + uLongf dstLen = compressBound ((uLongf)*rleUncompressedSize); + + if (Z_OK != ::compress2 + ((Bytef *)outDataPtr, + &dstLen, + (Bytef *)_rleBuffer, + (uLong)(*rleUncompressedSize), + 9)) + { + throw IEX_NAMESPACE::BaseExc ("Error compressing RLE'd data."); + } + + *rleCompressedSize = dstLen; + outDataPtr += *rleCompressedSize; + } + + // + // Flip the counters to XDR format + // + + for (int i = 0; i < NUM_SIZES_SINGLE; ++i) + { + Int64 src = *(((Int64 *)_outBuffer) + i); + char *dst = (char *)(((Int64 *)_outBuffer) + i); + + Xdr::write (dst, src); + } + + // + // We're done - compute the number of bytes we packed + // + + outPtr = _outBuffer; + + return static_cast(outDataPtr - _outBuffer + 1); +} + + +int +DwaCompressor::uncompress + (const char *inPtr, + int inSize, + int minY, + const char *&outPtr) +{ + return uncompress (inPtr, + inSize, + IMATH_NAMESPACE::Box2i (IMATH_NAMESPACE::V2i (_min[0], minY), + IMATH_NAMESPACE::V2i (_max[0], minY + numScanLines() - 1)), + outPtr); +} + + +int +DwaCompressor::uncompressTile + (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) +{ + return uncompress (inPtr, inSize, range, outPtr); +} + + +int +DwaCompressor::uncompress + (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) +{ + int minX = range.min.x; + int maxX = std::min (range.max.x, _max[0]); + int minY = range.min.y; + int maxY = std::min (range.max.y, _max[1]); + + int headerSize = NUM_SIZES_SINGLE*sizeof(Int64); + if (inSize < headerSize) + { + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + "(truncated header)."); + } + + // + // Flip the counters from XDR to NATIVE + // + + for (int i = 0; i < NUM_SIZES_SINGLE; ++i) + { + Int64 *dst = (((Int64 *)inPtr) + i); + const char *src = (char *)(((Int64 *)inPtr) + i); + + Xdr::read (src, *dst); + } + + // + // Unwind all the counter info + // + + const Int64 *inPtr64 = (const Int64*) inPtr; + + Int64 version = *(inPtr64 + VERSION); + Int64 unknownUncompressedSize = *(inPtr64 + UNKNOWN_UNCOMPRESSED_SIZE); + Int64 unknownCompressedSize = *(inPtr64 + UNKNOWN_COMPRESSED_SIZE); + Int64 acCompressedSize = *(inPtr64 + AC_COMPRESSED_SIZE); + Int64 dcCompressedSize = *(inPtr64 + DC_COMPRESSED_SIZE); + Int64 rleCompressedSize = *(inPtr64 + RLE_COMPRESSED_SIZE); + Int64 rleUncompressedSize = *(inPtr64 + RLE_UNCOMPRESSED_SIZE); + Int64 rleRawSize = *(inPtr64 + RLE_RAW_SIZE); + + Int64 totalAcUncompressedCount = *(inPtr64 + AC_UNCOMPRESSED_COUNT); + Int64 totalDcUncompressedCount = *(inPtr64 + DC_UNCOMPRESSED_COUNT); + + Int64 acCompression = *(inPtr64 + AC_COMPRESSION); + + Int64 compressedSize = unknownCompressedSize + + acCompressedSize + + dcCompressedSize + + rleCompressedSize; + + const char *dataPtr = inPtr + NUM_SIZES_SINGLE * sizeof(Int64); + + /* Both the sum and individual sizes are checked in case of overflow. */ + if (inSize < (headerSize + compressedSize) || + inSize < unknownCompressedSize || + inSize < acCompressedSize || + inSize < dcCompressedSize || + inSize < rleCompressedSize) + { + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + "(truncated file)."); + } + + if ((SInt64)unknownUncompressedSize < 0 || + (SInt64)unknownCompressedSize < 0 || + (SInt64)acCompressedSize < 0 || + (SInt64)dcCompressedSize < 0 || + (SInt64)rleCompressedSize < 0 || + (SInt64)rleUncompressedSize < 0 || + (SInt64)rleRawSize < 0 || + (SInt64)totalAcUncompressedCount < 0 || + (SInt64)totalDcUncompressedCount < 0) + { + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + " (corrupt header)."); + } + + if (version < 2) + initializeLegacyChannelRules(); + else + { + unsigned short ruleSize = 0; + Xdr::read(dataPtr, ruleSize); + + if (ruleSize < 0) + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + " (corrupt header file)."); + + headerSize += ruleSize; + if (inSize < headerSize + compressedSize) + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + " (truncated file)."); + + _channelRules.clear(); + ruleSize -= Xdr::size (); + while (ruleSize > 0) + { + Classifier rule(dataPtr, ruleSize); + + _channelRules.push_back(rule); + ruleSize -= rule.size(); + } + } + + + size_t outBufferSize = 0; + initializeBuffers(outBufferSize); + + // + // Allocate _outBuffer, if we haven't done so already + // + + if (_maxScanLineSize * numScanLines() > _outBufferSize) + { + _outBufferSize = _maxScanLineSize * numScanLines(); + if (_outBuffer != 0) + delete[] _outBuffer; + _outBuffer = new char[_maxScanLineSize * numScanLines()]; + } + + + char *outBufferEnd = _outBuffer; + + + // + // Find the start of the RLE packed AC components and + // the DC components for each channel. This will be handy + // if you want to decode the channels in parallel later on. + // + + char *packedAcBufferEnd = 0; + + if (_packedAcBuffer) + packedAcBufferEnd = _packedAcBuffer; + + char *packedDcBufferEnd = 0; + + if (_packedDcBuffer) + packedDcBufferEnd = _packedDcBuffer; + + // + // UNKNOWN data is packed first, followed by the + // Huffman-compressed AC, then the DC values, + // and then the zlib compressed RLE data. + // + + const char *compressedUnknownBuf = dataPtr; + + const char *compressedAcBuf = compressedUnknownBuf + + static_cast(unknownCompressedSize); + const char *compressedDcBuf = compressedAcBuf + + static_cast(acCompressedSize); + const char *compressedRleBuf = compressedDcBuf + + static_cast(dcCompressedSize); + + // + // Sanity check that the version is something we expect. Right now, + // we can decode version 0, 1, and 2. v1 adds 'end of block' symbols + // to the AC RLE. v2 adds channel classification rules at the + // start of the data block. + // + + if (version > 2) + throw IEX_NAMESPACE::InputExc ("Invalid version of compressed data block"); + + setupChannelData(minX, minY, maxX, maxY); + + // + // Uncompress the UNKNOWN data into _planarUncBuffer[UNKNOWN] + // + + if (unknownCompressedSize > 0) + { + if (unknownUncompressedSize > _planarUncBufferSize[UNKNOWN]) + { + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + "(corrupt header)."); + } + + uLongf outSize = (uLongf)unknownUncompressedSize; + + if (Z_OK != ::uncompress + ((Bytef *)_planarUncBuffer[UNKNOWN], + &outSize, + (Bytef *)compressedUnknownBuf, + (uLong)unknownCompressedSize)) + { + throw IEX_NAMESPACE::BaseExc("Error uncompressing UNKNOWN data."); + } + } + + // + // Uncompress the AC data into _packedAcBuffer + // + + if (acCompressedSize > 0) + { + if (totalAcUncompressedCount*sizeof(unsigned short) > _packedAcBufferSize) + { + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + "(corrupt header)."); + } + + // + // Don't trust the user to get it right, look in the file. + // + + switch (acCompression) + { + case STATIC_HUFFMAN: + + hufUncompress + (compressedAcBuf, + (int)acCompressedSize, + (unsigned short *)_packedAcBuffer, + (int)totalAcUncompressedCount); + + break; + + case DEFLATE: + { + uLongf destLen = + (int)(totalAcUncompressedCount) * sizeof (unsigned short); + + if (Z_OK != ::uncompress + ((Bytef *)_packedAcBuffer, + &destLen, + (Bytef *)compressedAcBuf, + (uLong)acCompressedSize)) + { + throw IEX_NAMESPACE::InputExc ("Data decompression (zlib) failed."); + } + + if (totalAcUncompressedCount * sizeof (unsigned short) != + destLen) + { + throw IEX_NAMESPACE::InputExc ("AC data corrupt."); + } + } + break; + + default: + + throw IEX_NAMESPACE::NoImplExc ("Unknown AC Compression"); + break; + } + } + + // + // Uncompress the DC data into _packedDcBuffer + // + + if (dcCompressedSize > 0) + { + if (totalDcUncompressedCount*sizeof(unsigned short) > _packedDcBufferSize) + { + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + "(corrupt header)."); + } + + if (_zip->uncompress + (compressedDcBuf, (int)dcCompressedSize, _packedDcBuffer) + != (int)totalDcUncompressedCount * sizeof (unsigned short)) + { + throw IEX_NAMESPACE::BaseExc("DC data corrupt."); + } + } + + // + // Uncompress the RLE data into _rleBuffer, then unRLE the results + // into _planarUncBuffer[RLE] + // + + if (rleRawSize > 0) + { + if (rleUncompressedSize > _rleBufferSize || + rleRawSize > _planarUncBufferSize[RLE]) + { + throw IEX_NAMESPACE::InputExc("Error uncompressing DWA data" + "(corrupt header)."); + } + + uLongf dstLen = (uLongf)rleUncompressedSize; + + if (Z_OK != ::uncompress + ((Bytef *)_rleBuffer, + &dstLen, + (Bytef *)compressedRleBuf, + (uLong)rleCompressedSize)) + { + throw IEX_NAMESPACE::BaseExc("Error uncompressing RLE data."); + } + + if (dstLen != rleUncompressedSize) + throw IEX_NAMESPACE::BaseExc("RLE data corrupted"); + + if (rleUncompress + ((int)rleUncompressedSize, + (int)rleRawSize, + (signed char *)_rleBuffer, + _planarUncBuffer[RLE]) != rleRawSize) + { + throw IEX_NAMESPACE::BaseExc("RLE data corrupted"); + } + } + + // + // Determine the start of each row in the output buffer + // + + std::vector decodedChannels (_channelData.size()); + std::vector< std::vector > rowPtrs (_channelData.size()); + + for (unsigned int chan = 0; chan < _channelData.size(); ++chan) + decodedChannels[chan] = false; + + outBufferEnd = _outBuffer; + + for (int y = minY; y <= maxY; ++y) + { + for (unsigned int chan = 0; chan < _channelData.size(); ++chan) + { + ChannelData *cd = &_channelData[chan]; + + if (IMATH_NAMESPACE::modp (y, cd->ySampling) != 0) + continue; + + rowPtrs[chan].push_back (outBufferEnd); + outBufferEnd += cd->width * OPENEXR_IMF_NAMESPACE::pixelTypeSize (cd->type); + } + } + + // + // Setup to decode each block of 3 channels that need to + // be handled together + // + + for (unsigned int csc = 0; csc < _cscSets.size(); ++csc) + { + int rChan = _cscSets[csc].idx[0]; + int gChan = _cscSets[csc].idx[1]; + int bChan = _cscSets[csc].idx[2]; + + + LossyDctDecoderCsc decoder + (rowPtrs[rChan], + rowPtrs[gChan], + rowPtrs[bChan], + packedAcBufferEnd, + packedDcBufferEnd, + get_dwaCompressorToLinear(), + _channelData[rChan].width, + _channelData[rChan].height, + _channelData[rChan].type, + _channelData[gChan].type, + _channelData[bChan].type); + + decoder.execute(); + + packedAcBufferEnd += + decoder.numAcValuesEncoded() * sizeof (unsigned short); + + packedDcBufferEnd += + decoder.numDcValuesEncoded() * sizeof (unsigned short); + + decodedChannels[rChan] = true; + decodedChannels[gChan] = true; + decodedChannels[bChan] = true; + } + + // + // Setup to handle the remaining channels by themselves + // + + for (unsigned int chan = 0; chan < _channelData.size(); ++chan) + { + if (decodedChannels[chan]) + continue; + + ChannelData *cd = &_channelData[chan]; + int pixelSize = OPENEXR_IMF_NAMESPACE::pixelTypeSize (cd->type); + + switch (cd->compression) + { + case LOSSY_DCT: + + // + // Setup a single-channel lossy DCT decoder pointing + // at the output buffer + // + + { + const unsigned short *linearLut = 0; + + if (!cd->pLinear) + linearLut = get_dwaCompressorToLinear(); + + LossyDctDecoder decoder + (rowPtrs[chan], + packedAcBufferEnd, + packedDcBufferEnd, + linearLut, + cd->width, + cd->height, + cd->type); + + decoder.execute(); + + packedAcBufferEnd += + decoder.numAcValuesEncoded() * sizeof (unsigned short); + + packedDcBufferEnd += + decoder.numDcValuesEncoded() * sizeof (unsigned short); + } + + break; + + case RLE: + + // + // For the RLE case, the data has been un-RLE'd into + // planarUncRleEnd[], but is still split out by bytes. + // We need to rearrange the bytes back into the correct + // order in the output buffer; + // + + { + int row = 0; + + for (int y = minY; y <= maxY; ++y) + { + if (IMATH_NAMESPACE::modp (y, cd->ySampling) != 0) + continue; + + char *dst = rowPtrs[chan][row]; + + if (pixelSize == 2) + { + interleaveByte2 (dst, + cd->planarUncRleEnd[0], + cd->planarUncRleEnd[1], + cd->width); + + cd->planarUncRleEnd[0] += cd->width; + cd->planarUncRleEnd[1] += cd->width; + } + else + { + for (int x = 0; x < cd->width; ++x) + { + for (int byte = 0; byte < pixelSize; ++byte) + { + *dst++ = *cd->planarUncRleEnd[byte]++; + } + } + } + + row++; + } + } + + break; + + case UNKNOWN: + + // + // In the UNKNOWN case, data is already in planarUncBufferEnd + // and just needs to copied over to the output buffer + // + + { + int row = 0; + int dstScanlineSize = cd->width * OPENEXR_IMF_NAMESPACE::pixelTypeSize (cd->type); + + for (int y = minY; y <= maxY; ++y) + { + if (IMATH_NAMESPACE::modp (y, cd->ySampling) != 0) + continue; + + memcpy (rowPtrs[chan][row], + cd->planarUncBufferEnd, + dstScanlineSize); + + cd->planarUncBufferEnd += dstScanlineSize; + row++; + } + } + + break; + + default: + + throw IEX_NAMESPACE::NoImplExc ("Unhandled compression scheme case"); + break; + } + + decodedChannels[chan] = true; + } + + // + // Return a ptr to _outBuffer + // + + outPtr = _outBuffer; + return (int)(outBufferEnd - _outBuffer); +} + + +// static +void +DwaCompressor::initializeFuncs() +{ + convertFloatToHalf64 = convertFloatToHalf64_scalar; + fromHalfZigZag = fromHalfZigZag_scalar; + + CpuId cpuId; + + // + // Setup HALF <-> FLOAT conversion implementations + // + + if (cpuId.avx && cpuId.f16c) + { + convertFloatToHalf64 = convertFloatToHalf64_f16c; + fromHalfZigZag = fromHalfZigZag_f16c; + } + + // + // Setup inverse DCT implementations + // + + dctInverse8x8_0 = dctInverse8x8_scalar<0>; + dctInverse8x8_1 = dctInverse8x8_scalar<1>; + dctInverse8x8_2 = dctInverse8x8_scalar<2>; + dctInverse8x8_3 = dctInverse8x8_scalar<3>; + dctInverse8x8_4 = dctInverse8x8_scalar<4>; + dctInverse8x8_5 = dctInverse8x8_scalar<5>; + dctInverse8x8_6 = dctInverse8x8_scalar<6>; + dctInverse8x8_7 = dctInverse8x8_scalar<7>; + + if (cpuId.avx) + { + dctInverse8x8_0 = dctInverse8x8_avx<0>; + dctInverse8x8_1 = dctInverse8x8_avx<1>; + dctInverse8x8_2 = dctInverse8x8_avx<2>; + dctInverse8x8_3 = dctInverse8x8_avx<3>; + dctInverse8x8_4 = dctInverse8x8_avx<4>; + dctInverse8x8_5 = dctInverse8x8_avx<5>; + dctInverse8x8_6 = dctInverse8x8_avx<6>; + dctInverse8x8_7 = dctInverse8x8_avx<7>; + } + else if (cpuId.sse2) + { + dctInverse8x8_0 = dctInverse8x8_sse2<0>; + dctInverse8x8_1 = dctInverse8x8_sse2<1>; + dctInverse8x8_2 = dctInverse8x8_sse2<2>; + dctInverse8x8_3 = dctInverse8x8_sse2<3>; + dctInverse8x8_4 = dctInverse8x8_sse2<4>; + dctInverse8x8_5 = dctInverse8x8_sse2<5>; + dctInverse8x8_6 = dctInverse8x8_sse2<6>; + dctInverse8x8_7 = dctInverse8x8_sse2<7>; + } +} + + +// +// Handle channel classification and buffer allocation once we know +// how to classify channels +// + +void +DwaCompressor::initializeBuffers (size_t &outBufferSize) +{ + classifyChannels (_channels, _channelData, _cscSets); + + // + // _outBuffer needs to be big enough to hold all our + // compressed data - which could vary depending on what sort + // of channels we have. + // + + int maxOutBufferSize = 0; + int numLossyDctChans = 0; + int unknownBufferSize = 0; + int rleBufferSize = 0; + + int maxLossyDctAcSize = (int)ceil ((float)numScanLines() / 8.0f) * + (int)ceil ((float)(_max[0] - _min[0] + 1) / 8.0f) * + 63 * sizeof (unsigned short); + + int maxLossyDctDcSize = (int)ceil ((float)numScanLines() / 8.0f) * + (int)ceil ((float)(_max[0] - _min[0] + 1) / 8.0f) * + sizeof (unsigned short); + + for (unsigned int chan = 0; chan < _channelData.size(); ++chan) + { + switch (_channelData[chan].compression) + { + case LOSSY_DCT: + + // + // This is the size of the number of packed + // components, plus the requirements for + // maximum Huffman encoding size (for STATIC_HUFFMAN) + // or for zlib compression (for DEFLATE) + // + + maxOutBufferSize += std::max( + (int)(2 * maxLossyDctAcSize + 65536), + (int)compressBound (maxLossyDctAcSize) ); + numLossyDctChans++; + break; + + case RLE: + { + // + // RLE, if gone horribly wrong, could double the size + // of the source data. + // + + int rleAmount = 2 * numScanLines() * (_max[0] - _min[0] + 1) * + OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type); + + rleBufferSize += rleAmount; + } + break; + + + case UNKNOWN: + + unknownBufferSize += numScanLines() * (_max[0] - _min[0] + 1) * + OPENEXR_IMF_NAMESPACE::pixelTypeSize (_channelData[chan].type); + break; + + default: + + throw IEX_NAMESPACE::NoImplExc ("Unhandled compression scheme case"); + break; + } + } + + // + // Also, since the results of the RLE are packed into + // the output buffer, we need the extra room there. But + // we're going to zlib compress() the data we pack, + // which could take slightly more space + // + + maxOutBufferSize += (int)compressBound ((uLongf)rleBufferSize); + + // + // And the same goes for the UNKNOWN data + // + + maxOutBufferSize += (int)compressBound ((uLongf)unknownBufferSize); + + // + // Allocate a zip/deflate compressor big enought to hold the DC data + // and include it's compressed results in the size requirements + // for our output buffer + // + + if (_zip == 0) + _zip = new Zip (maxLossyDctDcSize * numLossyDctChans); + else if (_zip->maxRawSize() < maxLossyDctDcSize * numLossyDctChans) + { + delete _zip; + _zip = new Zip (maxLossyDctDcSize * numLossyDctChans); + } + + + maxOutBufferSize += _zip->maxCompressedSize(); + + // + // We also need to reserve space at the head of the buffer to + // write out the size of our various packed and compressed data. + // + + maxOutBufferSize += NUM_SIZES_SINGLE * sizeof (Int64); + + + // + // Later, we're going to hijack outBuffer for the result of + // both encoding and decoding. So it needs to be big enough + // to hold either a buffers' worth of uncompressed or + // compressed data + // + // For encoding, we'll need _outBuffer to hold maxOutBufferSize bytes, + // but for decoding, we only need it to be maxScanLineSize*numScanLines. + // Cache the max size for now, and alloc the buffer when we either + // encode or decode. + // + + outBufferSize = maxOutBufferSize; + + + // + // _packedAcBuffer holds the quantized DCT coefficients prior + // to Huffman encoding + // + + if (maxLossyDctAcSize * numLossyDctChans > _packedAcBufferSize) + { + _packedAcBufferSize = maxLossyDctAcSize * numLossyDctChans; + if (_packedAcBuffer != 0) + delete[] _packedAcBuffer; + _packedAcBuffer = new char[_packedAcBufferSize]; + } + + // + // _packedDcBuffer holds one quantized DCT coef per 8x8 block + // + + if (maxLossyDctDcSize * numLossyDctChans > _packedDcBufferSize) + { + _packedDcBufferSize = maxLossyDctDcSize * numLossyDctChans; + if (_packedDcBuffer != 0) + delete[] _packedDcBuffer; + _packedDcBuffer = new char[_packedDcBufferSize]; + } + + if (rleBufferSize > _rleBufferSize) + { + _rleBufferSize = rleBufferSize; + if (_rleBuffer != 0) + delete[] _rleBuffer; + _rleBuffer = new char[rleBufferSize]; + } + + // + // The planar uncompressed buffer will hold float data for LOSSY_DCT + // compressed values, and whatever the native type is for other + // channels. We're going to use this to hold data in a planar + // format, as opposed to the native interleaved format we take + // into compress() and give back from uncompress(). + // + // This also makes it easier to compress the UNKNOWN and RLE data + // all in one swoop (for each compression scheme). + // + + int planarUncBufferSize[NUM_COMPRESSOR_SCHEMES]; + for (int i=0; i 0) + { + planarUncBufferSize[UNKNOWN] = + compressBound ((uLongf)planarUncBufferSize[UNKNOWN]); + } + + for (int i = 0; i < NUM_COMPRESSOR_SCHEMES; ++i) + { + if (planarUncBufferSize[i] > _planarUncBufferSize[i]) + { + _planarUncBufferSize[i] = planarUncBufferSize[i]; + if (_planarUncBuffer[i] != 0) + delete[] _planarUncBuffer[i]; + _planarUncBuffer[i] = new char[planarUncBufferSize[i]]; + } + } +} + + +// +// Setup channel classification rules to use when writing files +// + +void +DwaCompressor::initializeDefaultChannelRules () +{ + _channelRules.clear(); + + _channelRules.push_back (Classifier ("R", LOSSY_DCT, HALF, 0, false)); + _channelRules.push_back (Classifier ("R", LOSSY_DCT, FLOAT, 0, false)); + _channelRules.push_back (Classifier ("G", LOSSY_DCT, HALF, 1, false)); + _channelRules.push_back (Classifier ("G", LOSSY_DCT, FLOAT, 1, false)); + _channelRules.push_back (Classifier ("B", LOSSY_DCT, HALF, 2, false)); + _channelRules.push_back (Classifier ("B", LOSSY_DCT, FLOAT, 2, false)); + + _channelRules.push_back (Classifier ("Y", LOSSY_DCT, HALF, -1, false)); + _channelRules.push_back (Classifier ("Y", LOSSY_DCT, FLOAT, -1, false)); + _channelRules.push_back (Classifier ("BY", LOSSY_DCT, HALF, -1, false)); + _channelRules.push_back (Classifier ("BY", LOSSY_DCT, FLOAT, -1, false)); + _channelRules.push_back (Classifier ("RY", LOSSY_DCT, HALF, -1, false)); + _channelRules.push_back (Classifier ("RY", LOSSY_DCT, FLOAT, -1, false)); + + _channelRules.push_back (Classifier ("A", RLE, UINT, -1, false)); + _channelRules.push_back (Classifier ("A", RLE, HALF, -1, false)); + _channelRules.push_back (Classifier ("A", RLE, FLOAT, -1, false)); +} + + +// +// Setup channel classification rules when reading files with VERSION < 2 +// + +void +DwaCompressor::initializeLegacyChannelRules () +{ + _channelRules.clear(); + + _channelRules.push_back (Classifier ("r", LOSSY_DCT, HALF, 0, true)); + _channelRules.push_back (Classifier ("r", LOSSY_DCT, FLOAT, 0, true)); + _channelRules.push_back (Classifier ("red", LOSSY_DCT, HALF, 0, true)); + _channelRules.push_back (Classifier ("red", LOSSY_DCT, FLOAT, 0, true)); + _channelRules.push_back (Classifier ("g", LOSSY_DCT, HALF, 1, true)); + _channelRules.push_back (Classifier ("g", LOSSY_DCT, FLOAT, 1, true)); + _channelRules.push_back (Classifier ("grn", LOSSY_DCT, HALF, 1, true)); + _channelRules.push_back (Classifier ("grn", LOSSY_DCT, FLOAT, 1, true)); + _channelRules.push_back (Classifier ("green", LOSSY_DCT, HALF, 1, true)); + _channelRules.push_back (Classifier ("green", LOSSY_DCT, FLOAT, 1, true)); + _channelRules.push_back (Classifier ("b", LOSSY_DCT, HALF, 2, true)); + _channelRules.push_back (Classifier ("b", LOSSY_DCT, FLOAT, 2, true)); + _channelRules.push_back (Classifier ("blu", LOSSY_DCT, HALF, 2, true)); + _channelRules.push_back (Classifier ("blu", LOSSY_DCT, FLOAT, 2, true)); + _channelRules.push_back (Classifier ("blue", LOSSY_DCT, HALF, 2, true)); + _channelRules.push_back (Classifier ("blue", LOSSY_DCT, FLOAT, 2, true)); + + _channelRules.push_back (Classifier ("y", LOSSY_DCT, HALF, -1, true)); + _channelRules.push_back (Classifier ("y", LOSSY_DCT, FLOAT, -1, true)); + _channelRules.push_back (Classifier ("by", LOSSY_DCT, HALF, -1, true)); + _channelRules.push_back (Classifier ("by", LOSSY_DCT, FLOAT, -1, true)); + _channelRules.push_back (Classifier ("ry", LOSSY_DCT, HALF, -1, true)); + _channelRules.push_back (Classifier ("ry", LOSSY_DCT, FLOAT, -1, true)); + _channelRules.push_back (Classifier ("a", RLE, UINT, -1, true)); + _channelRules.push_back (Classifier ("a", RLE, HALF, -1, true)); + _channelRules.push_back (Classifier ("a", RLE, FLOAT, -1, true)); +} + + +// +// Given a set of rules and ChannelData, figure out which rules apply +// + +void +DwaCompressor::relevantChannelRules (std::vector &rules) const +{ + rules.clear(); + + std::vector suffixes; + + for (size_t cd = 0; cd < _channelData.size(); ++cd) + { + std::string suffix = _channelData[cd].name; + size_t lastDot = suffix.find_last_of ('.'); + + if (lastDot != std::string::npos) + suffix = suffix.substr (lastDot+1, std::string::npos); + + suffixes.push_back(suffix); + } + + + for (size_t i = 0; i < _channelRules.size(); ++i) + { + for (size_t cd = 0; cd < _channelData.size(); ++cd) + { + if (_channelRules[i].match (suffixes[cd], _channelData[cd].type )) + { + rules.push_back (_channelRules[i]); + break; + } + } + } +} + + +// +// Take our initial list of channels, and cache the contents. +// +// Determine approprate compression schemes for each channel, +// and figure out which sets should potentially be CSC'ed +// prior to lossy compression. +// + +void +DwaCompressor::classifyChannels + (ChannelList channels, + std::vector &chanData, + std::vector &cscData) +{ + // + // prefixMap used to map channel name prefixes to + // potential CSC-able sets of channels. + // + + std::map prefixMap; + std::vector tmpCscSet; + + unsigned int numChan = 0; + + for (ChannelList::Iterator c = channels.begin(); c != channels.end(); ++c) + numChan++; + + if (numChan) + chanData.resize (numChan); + + // + // Cache the relevant data from the channel structs. + // + + unsigned int offset = 0; + + for (ChannelList::Iterator c = channels.begin(); c != channels.end(); ++c) + { + chanData[offset].name = std::string (c.name()); + chanData[offset].compression = UNKNOWN; + chanData[offset].xSampling = c.channel().xSampling; + chanData[offset].ySampling = c.channel().ySampling; + chanData[offset].type = c.channel().type; + chanData[offset].pLinear = c.channel().pLinear; + + offset++; + } + + // + // Try and figure out which channels should be + // compressed by which means. + // + + for (offset = 0; offset::iterator + theSet = prefixMap.find (prefix); + + if (theSet == prefixMap.end()) + { + DwaCompressor::CscChannelSet tmpSet; + + tmpSet.idx[0] = + tmpSet.idx[1] = + tmpSet.idx[2] = -1; + + prefixMap[prefix] = tmpSet; + } + + // + // Check the suffix against the list of classifications + // we defined previously. If the _cscIdx is not negative, + // it indicates that we should be part of a CSC group. + // + + for (std::vector::iterator i = _channelRules.begin(); + i != _channelRules.end(); + ++i) + { + if ( i->match(suffix, chanData[offset].type) ) + { + chanData[offset].compression = i->_scheme; + + if ( i->_cscIdx >= 0) + prefixMap[prefix].idx[i->_cscIdx] = offset; + } + } + } + + // + // Finally, try and find RGB sets of channels which + // can be CSC'ed to a Y'CbCr space prior to loss, for + // better compression. + // + // Walk over our set of candidates, and see who has + // all three channels defined (and has common sampling + // patterns, etc). + // + + for (std::map::iterator + theItem = prefixMap.begin(); theItem != prefixMap.end(); + ++theItem) + { + int red = (*theItem).second.idx[0]; + int grn = (*theItem).second.idx[1]; + int blu = (*theItem).second.idx[2]; + + if ((red < 0) || (grn < 0) || (blu < 0)) + continue; + + if ((chanData[red].xSampling != chanData[grn].xSampling) || + (chanData[red].xSampling != chanData[blu].xSampling) || + (chanData[grn].xSampling != chanData[blu].xSampling) || + (chanData[red].ySampling != chanData[grn].ySampling) || + (chanData[red].ySampling != chanData[blu].ySampling) || + (chanData[grn].ySampling != chanData[blu].ySampling)) + { + continue; + } + + tmpCscSet.push_back ((*theItem).second); + } + + size_t numCsc = tmpCscSet.size(); + + if (numCsc) + cscData.resize(numCsc); + + for (offset = 0; offset < numCsc; ++offset) + cscData[offset] = tmpCscSet[offset]; +} + + + +// +// Setup some buffer pointers, determine channel sizes, things +// like that. +// + +void +DwaCompressor::setupChannelData (int minX, int minY, int maxX, int maxY) +{ + char *planarUncBuffer[NUM_COMPRESSOR_SCHEMES]; + + for (int i=0; iwidth = OPENEXR_IMF_NAMESPACE::numSamples (cd->xSampling, minX, maxX); + cd->height = OPENEXR_IMF_NAMESPACE::numSamples (cd->ySampling, minY, maxY); + + cd->planarUncSize = + cd->width * cd->height * OPENEXR_IMF_NAMESPACE::pixelTypeSize (cd->type); + + cd->planarUncBuffer = planarUncBuffer[cd->compression]; + cd->planarUncBufferEnd = cd->planarUncBuffer; + + cd->planarUncRle[0] = cd->planarUncBuffer; + cd->planarUncRleEnd[0] = cd->planarUncRle[0]; + + for (int byte = 1; byte < OPENEXR_IMF_NAMESPACE::pixelTypeSize(cd->type); ++byte) + { + cd->planarUncRle[byte] = + cd->planarUncRle[byte-1] + cd->width * cd->height; + + cd->planarUncRleEnd[byte] = + cd->planarUncRle[byte]; + } + + cd->planarUncType = cd->type; + + if (cd->compression == LOSSY_DCT) + { + cd->planarUncType = FLOAT; + } + else + { + planarUncBuffer[cd->compression] += + cd->width * cd->height * OPENEXR_IMF_NAMESPACE::pixelTypeSize (cd->planarUncType); + } + } +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfDwaCompressor.h b/3rdparty/openexr/IlmImf/ImfDwaCompressor.h new file mode 100644 index 0000000000..421490e903 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDwaCompressor.h @@ -0,0 +1,219 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2009-2014 DreamWorks Animation LLC. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of DreamWorks Animation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMF_DWA_COMRESSOR_H +#define INCLUDED_IMF_DWA_COMRESSOR_H + +//------------------------------------------------------------------------------ +// +// class DwaCompressor -- Store lossy RGB data by quantizing DCT components. +// +//------------------------------------------------------------------------------ + +#include +#include + +#include "ImfInt64.h" +#include "ImfZip.h" +#include "ImfChannelList.h" +#include "ImfCompressor.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class DwaCompressor: public Compressor +{ + public: + + enum AcCompression + { + STATIC_HUFFMAN, + DEFLATE, + }; + + + IMF_EXPORT + DwaCompressor (const Header &hdr, + int maxScanLineSize, + int numScanLines, // ideally is a multiple of 8 + AcCompression acCompression); + + IMF_EXPORT + virtual ~DwaCompressor (); + + IMF_EXPORT + virtual int numScanLines () const; + + IMF_EXPORT + virtual OPENEXR_IMF_NAMESPACE::Compressor::Format format () const; + + IMF_EXPORT + virtual int compress (const char *inPtr, + int inSize, + int minY, + const char *&outPtr); + + IMF_EXPORT + virtual int compressTile (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + + IMF_EXPORT + virtual int uncompress (const char *inPtr, + int inSize, + int minY, + const char *&outPtr); + + IMF_EXPORT + virtual int uncompressTile (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + + IMF_EXPORT + static void initializeFuncs (); + + private: + + struct ChannelData; + struct CscChannelSet; + struct Classifier; + + class LossyDctDecoderBase; + class LossyDctDecoder; + class LossyDctDecoderCsc; + + class LossyDctEncoderBase; + class LossyDctEncoder; + class LossyDctEncoderCsc; + + enum CompressorScheme + { + UNKNOWN = 0, + LOSSY_DCT, + RLE, + + NUM_COMPRESSOR_SCHEMES + }; + + // + // Per-chunk compressed data sizes, one value per chunk + // + + enum DataSizesSingle + { + VERSION = 0, // Version number: + // 0: classic + // 1: adds "end of block" to the AC RLE + + UNKNOWN_UNCOMPRESSED_SIZE, // Size of leftover data, uncompressed. + UNKNOWN_COMPRESSED_SIZE, // Size of leftover data, zlib compressed. + + AC_COMPRESSED_SIZE, // AC RLE + Huffman size + DC_COMPRESSED_SIZE, // DC + Deflate size + RLE_COMPRESSED_SIZE, // RLE + Deflate data size + RLE_UNCOMPRESSED_SIZE, // RLE'd data size + RLE_RAW_SIZE, // Un-RLE'd data size + + AC_UNCOMPRESSED_COUNT, // AC RLE number of elements + DC_UNCOMPRESSED_COUNT, // DC number of elements + + AC_COMPRESSION, // AC compression strategy + NUM_SIZES_SINGLE + }; + + AcCompression _acCompression; + + int _maxScanLineSize; + int _numScanLines; + int _min[2], _max[2]; + + ChannelList _channels; + std::vector _channelData; + std::vector _cscSets; + std::vector _channelRules; + + char *_packedAcBuffer; + size_t _packedAcBufferSize; + char *_packedDcBuffer; + size_t _packedDcBufferSize; + char *_rleBuffer; + size_t _rleBufferSize; + char *_outBuffer; + size_t _outBufferSize; + char *_planarUncBuffer[NUM_COMPRESSOR_SCHEMES]; + size_t _planarUncBufferSize[NUM_COMPRESSOR_SCHEMES]; + + Zip *_zip; + float _dwaCompressionLevel; + + int compress (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + + int uncompress (const char *inPtr, + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + + void initializeBuffers (size_t&); + void initializeDefaultChannelRules (); + void initializeLegacyChannelRules (); + + void relevantChannelRules( std::vector &) const; + + // + // Populate our cached version of the channel data with + // data from the real channel list. We want to + // copy over attributes, determine compression schemes + // releveant for the channel type, and find sets of + // channels to be compressed from Y'CbCr data instead + // of R'G'B'. + // + + void classifyChannels (ChannelList channels, + std::vector &chanData, + std::vector &cscData); + + // + // Compute various buffer pointers for each channel + // + + void setupChannelData (int minX, int minY, int maxX, int maxY); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfDwaCompressorSimd.h b/3rdparty/openexr/IlmImf/ImfDwaCompressorSimd.h new file mode 100644 index 0000000000..c14ae7a323 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfDwaCompressorSimd.h @@ -0,0 +1,2172 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2009-2014 DreamWorks Animation LLC. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of DreamWorks Animation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMF_DWACOMPRESSORSIMD_H_HAS_BEEN_INCLUDED +#define IMF_DWACOMPRESSORSIMD_H_HAS_BEEN_INCLUDED + +// +// Various SSE accelerated functions, used by Imf::DwaCompressor. +// These have been separated into a separate .h file, as the fast +// paths are done with template specialization. +// +// Unless otherwise noted, all pointers are assumed to be 32-byte +// aligned. Unaligned pointers may risk seg-faulting. +// + +#include "ImfNamespace.h" +#include "ImfSimd.h" +#include "ImfSystemSpecific.h" +#include "OpenEXRConfig.h" + +#include +#include + +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +#define _SSE_ALIGNMENT 32 +#define _SSE_ALIGNMENT_MASK 0x0F +#define _AVX_ALIGNMENT_MASK 0x1F + +// +// Test if we should enable GCC inline asm paths for AVX +// + +#ifdef OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX + + #define IMF_HAVE_GCC_INLINEASM + + #ifdef __LP64__ + #define IMF_HAVE_GCC_INLINEASM_64 + #endif /* __LP64__ */ + +#endif /* OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX */ + +// +// A simple 64-element array, aligned properly for SIMD access. +// + +template +class SimdAlignedBuffer64 +{ + public: + + SimdAlignedBuffer64(): _buffer (0), _handle (0) + { + alloc(); + } + + SimdAlignedBuffer64(const SimdAlignedBuffer64 &rhs): _handle(0) + { + alloc(); + memcpy (_buffer, rhs._buffer, 64 * sizeof (T)); + } + + SimdAlignedBuffer64 &operator=(const SimdAlignedBuffer64 &rhs) + { + memcpy (_buffer, rhs._buffer, 64 * sizeof (T)); + return *this; + } + +#if __cplusplus >= 201103L + SimdAlignedBuffer64(SimdAlignedBuffer64 &&rhs) noexcept + : _handle(rhs._handle), _buffer(rhs._buffer) + { + rhs._handle = nullptr; + rhs._buffer = nullptr; + } + + SimdAlignedBuffer64 &operator=(SimdAlignedBuffer64 &&rhs) noexcept + { + std::swap(_handle, rhs._handle); + std::swap(_buffer, rhs._buffer); + return *this; + } +#endif + ~SimdAlignedBuffer64 () + { + if (_handle) + EXRFreeAligned (_handle); + _handle = 0; + _buffer = 0; + } + + void alloc() + { + // + // Try EXRAllocAligned first - but it might fallback to + // unaligned allocs. If so, overalloc. + // + + _handle = (char *) EXRAllocAligned + (64 * sizeof(T), _SSE_ALIGNMENT); + + if (((size_t)_handle & (_SSE_ALIGNMENT - 1)) == 0) + { + _buffer = (T *)_handle; + return; + } + + EXRFreeAligned(_handle); + _handle = (char *) EXRAllocAligned + (64 * sizeof(T) + _SSE_ALIGNMENT, _SSE_ALIGNMENT); + + char *aligned = _handle; + + while ((size_t)aligned & (_SSE_ALIGNMENT - 1)) + aligned++; + + _buffer = (T *)aligned; + } + + T *_buffer; + + private: + + char *_handle; +}; + +typedef SimdAlignedBuffer64 SimdAlignedBuffer64f; +typedef SimdAlignedBuffer64 SimdAlignedBuffer64us; + +namespace { + +// +// Color space conversion, Inverse 709 CSC, Y'CbCr -> R'G'B' +// + +void +csc709Inverse (float &comp0, float &comp1, float &comp2) +{ + float src[3]; + + src[0] = comp0; + src[1] = comp1; + src[2] = comp2; + + comp0 = src[0] + 1.5747f * src[2]; + comp1 = src[0] - 0.1873f * src[1] - 0.4682f * src[2]; + comp2 = src[0] + 1.8556f * src[1]; +} + +#ifndef IMF_HAVE_SSE2 + + +// +// Scalar color space conversion, based on 709 primiary chromaticies. +// No scaling or offsets, just the matrix +// + +void +csc709Inverse64 (float *comp0, float *comp1, float *comp2) +{ + for (int i = 0; i < 64; ++i) + csc709Inverse (comp0[i], comp1[i], comp2[i]); +} + +#else /* IMF_HAVE_SSE2 */ + +// +// SSE2 color space conversion +// + +void +csc709Inverse64 (float *comp0, float *comp1, float *comp2) +{ + __m128 c0 = { 1.5747f, 1.5747f, 1.5747f, 1.5747f}; + __m128 c1 = { 1.8556f, 1.8556f, 1.8556f, 1.8556f}; + __m128 c2 = {-0.1873f, -0.1873f, -0.1873f, -0.1873f}; + __m128 c3 = {-0.4682f, -0.4682f, -0.4682f, -0.4682f}; + + __m128 *r = (__m128 *)comp0; + __m128 *g = (__m128 *)comp1; + __m128 *b = (__m128 *)comp2; + __m128 src[3]; + + #define CSC_INVERSE_709_SSE2_LOOP(i) \ + src[0] = r[i]; \ + src[1] = g[i]; \ + src[2] = b[i]; \ + \ + r[i] = _mm_add_ps (r[i], _mm_mul_ps (src[2], c0)); \ + \ + g[i] = _mm_mul_ps (g[i], c2); \ + src[2] = _mm_mul_ps (src[2], c3); \ + g[i] = _mm_add_ps (g[i], src[0]); \ + g[i] = _mm_add_ps (g[i], src[2]); \ + \ + b[i] = _mm_mul_ps (c1, src[1]); \ + b[i] = _mm_add_ps (b[i], src[0]); + + CSC_INVERSE_709_SSE2_LOOP (0) + CSC_INVERSE_709_SSE2_LOOP (1) + CSC_INVERSE_709_SSE2_LOOP (2) + CSC_INVERSE_709_SSE2_LOOP (3) + + CSC_INVERSE_709_SSE2_LOOP (4) + CSC_INVERSE_709_SSE2_LOOP (5) + CSC_INVERSE_709_SSE2_LOOP (6) + CSC_INVERSE_709_SSE2_LOOP (7) + + CSC_INVERSE_709_SSE2_LOOP (8) + CSC_INVERSE_709_SSE2_LOOP (9) + CSC_INVERSE_709_SSE2_LOOP (10) + CSC_INVERSE_709_SSE2_LOOP (11) + + CSC_INVERSE_709_SSE2_LOOP (12) + CSC_INVERSE_709_SSE2_LOOP (13) + CSC_INVERSE_709_SSE2_LOOP (14) + CSC_INVERSE_709_SSE2_LOOP (15) +} + +#endif /* IMF_HAVE_SSE2 */ + + +// +// Color space conversion, Forward 709 CSC, R'G'B' -> Y'CbCr +// +// Simple FPU color space conversion. Based on the 709 +// primary chromaticies, with no scaling or offsets. +// + +void +csc709Forward64 (float *comp0, float *comp1, float *comp2) +{ + float src[3]; + + for (int i = 0; i<64; ++i) + { + src[0] = comp0[i]; + src[1] = comp1[i]; + src[2] = comp2[i]; + + comp0[i] = 0.2126f * src[0] + 0.7152f * src[1] + 0.0722f * src[2]; + comp1[i] = -0.1146f * src[0] - 0.3854f * src[1] + 0.5000f * src[2]; + comp2[i] = 0.5000f * src[0] - 0.4542f * src[1] - 0.0458f * src[2]; + } +} + + +// +// Byte interleaving of 2 byte arrays: +// src0 = AAAA +// src1 = BBBB +// dst = ABABABAB +// +// numBytes is the size of each of the source buffers +// + +#ifndef IMF_HAVE_SSE2 + +// +// Scalar default implementation +// + +void +interleaveByte2 (char *dst, char *src0, char *src1, int numBytes) +{ + for (int x = 0; x < numBytes; ++x) + { + dst[2 * x] = src0[x]; + dst[2 * x + 1] = src1[x]; + } +} + +#else /* IMF_HAVE_SSE2 */ + +// +// SSE2 byte interleaving +// + +void +interleaveByte2 (char *dst, char *src0, char *src1, int numBytes) +{ + int dstAlignment = (size_t)dst % 16; + int src0Alignment = (size_t)src0 % 16; + int src1Alignment = (size_t)src1 % 16; + + __m128i *dst_epi8 = (__m128i*)dst; + __m128i *src0_epi8 = (__m128i*)src0; + __m128i *src1_epi8 = (__m128i*)src1; + int sseWidth = numBytes / 16; + + if ((!dstAlignment) && (!src0Alignment) && (!src1Alignment)) + { + __m128i tmp0, tmp1; + + // + // Aligned loads and stores + // + + for (int x = 0; x < sseWidth; ++x) + { + tmp0 = src0_epi8[x]; + tmp1 = src1_epi8[x]; + + _mm_stream_si128 (&dst_epi8[2 * x], + _mm_unpacklo_epi8 (tmp0, tmp1)); + + _mm_stream_si128 (&dst_epi8[2 * x + 1], + _mm_unpackhi_epi8 (tmp0, tmp1)); + } + + // + // Then do run the leftovers one at a time + // + + for (int x = 16 * sseWidth; x < numBytes; ++x) + { + dst[2 * x] = src0[x]; + dst[2 * x + 1] = src1[x]; + } + } + else if ((!dstAlignment) && (src0Alignment == 8) && (src1Alignment == 8)) + { + // + // Aligned stores, but catch up a few values so we can + // use aligned loads + // + + for (int x = 0; x < std::min (numBytes, 8); ++x) + { + dst[2 * x] = src0[x]; + dst[2 * x + 1] = src1[x]; + } + + if (numBytes > 8) + { + dst_epi8 = (__m128i*)&dst[16]; + src0_epi8 = (__m128i*)&src0[8]; + src1_epi8 = (__m128i*)&src1[8]; + sseWidth = (numBytes - 8) / 16; + + for (int x=0; x half float conversion +// +// To enable F16C based conversion, we can't rely on compile-time +// detection, hence the multiple defined versions. Pick one based +// on runtime cpuid detection. +// + +// +// Default boring conversion +// + +void +convertFloatToHalf64_scalar (unsigned short *dst, float *src) +{ + for (int i=0; i<64; ++i) + dst[i] = ((half)src[i]).bits(); +} + + +// +// F16C conversion - Assumes aligned src and dst +// + +void +convertFloatToHalf64_f16c (unsigned short *dst, float *src) +{ + // + // Ordinarly, I'd avoid using inline asm and prefer intrinsics. + // However, in order to get the intrinsics, we need to tell + // the compiler to generate VEX instructions. + // + // (On the GCC side, -mf16c goes ahead and activates -mavc, + // resulting in VEX code. Without -mf16c, no intrinsics..) + // + // Now, it's quite likely that we'll find ourselves in situations + // where we want to build *without* VEX, in order to maintain + // maximum compatability. But to get there with intrinsics, + // we'd need to break out code into a separate file. Bleh. + // I'll take the asm. + // + + #if defined IMF_HAVE_GCC_INLINEASM + __asm__ + ("vmovaps (%0), %%ymm0 \n" + "vmovaps 0x20(%0), %%ymm1 \n" + "vmovaps 0x40(%0), %%ymm2 \n" + "vmovaps 0x60(%0), %%ymm3 \n" + "vcvtps2ph $0, %%ymm0, %%xmm0 \n" + "vcvtps2ph $0, %%ymm1, %%xmm1 \n" + "vcvtps2ph $0, %%ymm2, %%xmm2 \n" + "vcvtps2ph $0, %%ymm3, %%xmm3 \n" + "vmovdqa %%xmm0, 0x00(%1) \n" + "vmovdqa %%xmm1, 0x10(%1) \n" + "vmovdqa %%xmm2, 0x20(%1) \n" + "vmovdqa %%xmm3, 0x30(%1) \n" + "vmovaps 0x80(%0), %%ymm0 \n" + "vmovaps 0xa0(%0), %%ymm1 \n" + "vmovaps 0xc0(%0), %%ymm2 \n" + "vmovaps 0xe0(%0), %%ymm3 \n" + "vcvtps2ph $0, %%ymm0, %%xmm0 \n" + "vcvtps2ph $0, %%ymm1, %%xmm1 \n" + "vcvtps2ph $0, %%ymm2, %%xmm2 \n" + "vcvtps2ph $0, %%ymm3, %%xmm3 \n" + "vmovdqa %%xmm0, 0x40(%1) \n" + "vmovdqa %%xmm1, 0x50(%1) \n" + "vmovdqa %%xmm2, 0x60(%1) \n" + "vmovdqa %%xmm3, 0x70(%1) \n" + #ifndef __AVX__ + "vzeroupper \n" + #endif /* __AVX__ */ + : /* Output */ + : /* Input */ "r"(src), "r"(dst) + #ifndef __AVX__ + : /* Clobber */ "%xmm0", "%xmm1", "%xmm2", "%xmm3", "memory" + #else + : /* Clobber */ "%ymm0", "%ymm1", "%ymm2", "%ymm3", "memory" + #endif /* __AVX__ */ + ); + #else + convertFloatToHalf64_scalar (dst, src); + #endif /* IMF_HAVE_GCC_INLINEASM */ +} + + +// +// Convert an 8x8 block of HALF from zig-zag order to +// FLOAT in normal order. The order we want is: +// +// src dst +// 0 1 2 3 4 5 6 7 0 1 5 6 14 15 27 28 +// 8 9 10 11 12 13 14 15 2 4 7 13 16 26 29 42 +// 16 17 18 19 20 21 22 23 3 8 12 17 25 30 41 43 +// 24 25 26 27 28 29 30 31 9 11 18 24 31 40 44 53 +// 32 33 34 35 36 37 38 39 10 19 23 32 39 45 52 54 +// 40 41 42 43 44 45 46 47 20 22 33 38 46 51 55 60 +// 48 49 50 51 52 53 54 55 21 34 37 47 50 56 59 61 +// 56 57 58 59 60 61 62 63 35 36 48 49 57 58 62 63 +// + +void +fromHalfZigZag_scalar (unsigned short *src, float *dst) +{ + half *srcHalf = (half *)src; + + dst[0] = (float)srcHalf[0]; + dst[1] = (float)srcHalf[1]; + dst[2] = (float)srcHalf[5]; + dst[3] = (float)srcHalf[6]; + dst[4] = (float)srcHalf[14]; + dst[5] = (float)srcHalf[15]; + dst[6] = (float)srcHalf[27]; + dst[7] = (float)srcHalf[28]; + dst[8] = (float)srcHalf[2]; + dst[9] = (float)srcHalf[4]; + + dst[10] = (float)srcHalf[7]; + dst[11] = (float)srcHalf[13]; + dst[12] = (float)srcHalf[16]; + dst[13] = (float)srcHalf[26]; + dst[14] = (float)srcHalf[29]; + dst[15] = (float)srcHalf[42]; + dst[16] = (float)srcHalf[3]; + dst[17] = (float)srcHalf[8]; + dst[18] = (float)srcHalf[12]; + dst[19] = (float)srcHalf[17]; + + dst[20] = (float)srcHalf[25]; + dst[21] = (float)srcHalf[30]; + dst[22] = (float)srcHalf[41]; + dst[23] = (float)srcHalf[43]; + dst[24] = (float)srcHalf[9]; + dst[25] = (float)srcHalf[11]; + dst[26] = (float)srcHalf[18]; + dst[27] = (float)srcHalf[24]; + dst[28] = (float)srcHalf[31]; + dst[29] = (float)srcHalf[40]; + + dst[30] = (float)srcHalf[44]; + dst[31] = (float)srcHalf[53]; + dst[32] = (float)srcHalf[10]; + dst[33] = (float)srcHalf[19]; + dst[34] = (float)srcHalf[23]; + dst[35] = (float)srcHalf[32]; + dst[36] = (float)srcHalf[39]; + dst[37] = (float)srcHalf[45]; + dst[38] = (float)srcHalf[52]; + dst[39] = (float)srcHalf[54]; + + dst[40] = (float)srcHalf[20]; + dst[41] = (float)srcHalf[22]; + dst[42] = (float)srcHalf[33]; + dst[43] = (float)srcHalf[38]; + dst[44] = (float)srcHalf[46]; + dst[45] = (float)srcHalf[51]; + dst[46] = (float)srcHalf[55]; + dst[47] = (float)srcHalf[60]; + dst[48] = (float)srcHalf[21]; + dst[49] = (float)srcHalf[34]; + + dst[50] = (float)srcHalf[37]; + dst[51] = (float)srcHalf[47]; + dst[52] = (float)srcHalf[50]; + dst[53] = (float)srcHalf[56]; + dst[54] = (float)srcHalf[59]; + dst[55] = (float)srcHalf[61]; + dst[56] = (float)srcHalf[35]; + dst[57] = (float)srcHalf[36]; + dst[58] = (float)srcHalf[48]; + dst[59] = (float)srcHalf[49]; + + dst[60] = (float)srcHalf[57]; + dst[61] = (float)srcHalf[58]; + dst[62] = (float)srcHalf[62]; + dst[63] = (float)srcHalf[63]; +} + + +// +// If we can form the correct ordering in xmm registers, +// we can use F16C to convert from HALF -> FLOAT. However, +// making the correct order isn't trivial. +// +// We want to re-order a source 8x8 matrix from: +// +// 0 1 2 3 4 5 6 7 0 1 5 6 14 15 27 28 +// 8 9 10 11 12 13 14 15 2 4 7 13 16 26 29 42 +// 16 17 18 19 20 21 22 23 3 8 12 17 25 30 41 43 +// 24 25 26 27 28 29 30 31 9 11 18 24 31 40 44 53 (A) +// 32 33 34 35 36 37 38 39 --> 10 19 23 32 39 45 52 54 +// 40 41 42 43 44 45 46 47 20 22 33 38 46 51 55 60 +// 48 49 50 51 52 53 54 55 21 34 37 47 50 56 59 61 +// 56 57 58 59 60 61 62 63 35 36 48 49 57 58 62 63 +// +// Which looks like a mess, right? +// +// Now, check out the NE/SW diagonals of (A). Along those lines, +// we have runs of contiguous values! If we rewrite (A) a bit, we get: +// +// 0 +// 1 2 +// 5 4 3 +// 6 7 8 9 +// 14 13 12 11 10 +// 15 16 17 18 19 20 +// 27 26 25 24 23 22 21 (B) +// 28 29 30 31 32 33 34 35 +// 42 41 40 39 38 37 36 +// 43 44 45 46 47 48 +// 53 52 51 50 49 +// 54 55 56 57 +// 60 59 58 +// 61 62 +// 63 +// +// In this ordering, the columns are the rows (A). If we can 'transpose' +// (B), we'll achieve our goal. But we want this to fit nicely into +// xmm registers and still be able to load large runs efficiently. +// Also, notice that the odd rows are in ascending order, while +// the even rows are in descending order. +// +// If we 'fold' the bottom half up into the top, we can preserve ordered +// runs accross rows, and still keep all the correct values in columns. +// After transposing, we'll need to rotate things back into place. +// This gives us: +// +// 0 | 42 41 40 39 38 37 36 +// 1 2 | 43 44 45 46 47 48 +// 5 4 3 | 53 52 51 50 49 +// 6 7 8 9 | 54 55 56 57 (C) +// 14 13 12 11 10 | 60 59 58 +// 15 16 17 18 19 20 | 61 62 +// 27 26 25 24 23 22 21 | 61 +// 28 29 30 31 32 33 34 35 +// +// But hang on. We still have the backwards descending rows to deal with. +// Lets reverse the even rows so that all values are in ascending order +// +// 36 37 38 39 40 41 42 | 0 +// 1 2 | 43 44 45 46 47 48 +// 49 50 51 52 53 | 3 4 5 +// 6 7 8 9 | 54 55 56 57 (D) +// 58 59 60 | 10 11 12 13 14 +// 15 16 17 18 19 20 | 61 62 +// 61 | 21 22 23 24 25 26 27 +// 28 29 30 31 32 33 34 35 +// +// If we can form (D), we will then: +// 1) Reverse the even rows +// 2) Transpose +// 3) Rotate the rows +// +// and we'll have (A). +// + +void +fromHalfZigZag_f16c (unsigned short *src, float *dst) +{ + #if defined IMF_HAVE_GCC_INLINEASM_64 + __asm__ + + /* x3 <- 0 + * x8 <- [ 0- 7] + * x6 <- [56-63] + * x9 <- [21-28] + * x7 <- [28-35] + * x3 <- [ 6- 9] (lower half) */ + + ("vpxor %%xmm3, %%xmm3, %%xmm3 \n" + "vmovdqa (%0), %%xmm8 \n" + "vmovdqa 112(%0), %%xmm6 \n" + "vmovdqu 42(%0), %%xmm9 \n" + "vmovdqu 56(%0), %%xmm7 \n" + "vmovq 12(%0), %%xmm3 \n" + + /* Setup rows 0-2 of A in xmm0-xmm2 + * x1 <- x8 >> 16 (1 value) + * x2 <- x8 << 32 (2 values) + * x0 <- alignr([35-42], x8, 2) + * x1 <- blend(x1, [41-48]) + * x2 <- blend(x2, [49-56]) */ + + "vpsrldq $2, %%xmm8, %%xmm1 \n" + "vpslldq $4, %%xmm8, %%xmm2 \n" + "vpalignr $2, 70(%0), %%xmm8, %%xmm0 \n" + "vpblendw $0xfc, 82(%0), %%xmm1, %%xmm1 \n" + "vpblendw $0x1f, 98(%0), %%xmm2, %%xmm2 \n" + + /* Setup rows 4-6 of A in xmm4-xmm6 + * x4 <- x6 >> 32 (2 values) + * x5 <- x6 << 16 (1 value) + * x6 <- alignr(x6,x9,14) + * x4 <- blend(x4, [ 7-14]) + * x5 <- blend(x5, [15-22]) */ + + "vpsrldq $4, %%xmm6, %%xmm4 \n" + "vpslldq $2, %%xmm6, %%xmm5 \n" + "vpalignr $14, %%xmm6, %%xmm9, %%xmm6 \n" + "vpblendw $0xf8, 14(%0), %%xmm4, %%xmm4 \n" + "vpblendw $0x3f, 30(%0), %%xmm5, %%xmm5 \n" + + /* Load the upper half of row 3 into xmm3 + * x3 <- [54-57] (upper half) */ + + "vpinsrq $1, 108(%0), %%xmm3, %%xmm3\n" + + /* Reverse the even rows. We're not using PSHUFB as + * that requires loading an extra constant all the time, + * and we're alreadly pretty memory bound. + */ + + "vpshuflw $0x1b, %%xmm0, %%xmm0 \n" + "vpshuflw $0x1b, %%xmm2, %%xmm2 \n" + "vpshuflw $0x1b, %%xmm4, %%xmm4 \n" + "vpshuflw $0x1b, %%xmm6, %%xmm6 \n" + + "vpshufhw $0x1b, %%xmm0, %%xmm0 \n" + "vpshufhw $0x1b, %%xmm2, %%xmm2 \n" + "vpshufhw $0x1b, %%xmm4, %%xmm4 \n" + "vpshufhw $0x1b, %%xmm6, %%xmm6 \n" + + "vpshufd $0x4e, %%xmm0, %%xmm0 \n" + "vpshufd $0x4e, %%xmm2, %%xmm2 \n" + "vpshufd $0x4e, %%xmm4, %%xmm4 \n" + "vpshufd $0x4e, %%xmm6, %%xmm6 \n" + + /* Transpose xmm0-xmm7 into xmm8-xmm15 */ + + "vpunpcklwd %%xmm1, %%xmm0, %%xmm8 \n" + "vpunpcklwd %%xmm3, %%xmm2, %%xmm9 \n" + "vpunpcklwd %%xmm5, %%xmm4, %%xmm10 \n" + "vpunpcklwd %%xmm7, %%xmm6, %%xmm11 \n" + "vpunpckhwd %%xmm1, %%xmm0, %%xmm12 \n" + "vpunpckhwd %%xmm3, %%xmm2, %%xmm13 \n" + "vpunpckhwd %%xmm5, %%xmm4, %%xmm14 \n" + "vpunpckhwd %%xmm7, %%xmm6, %%xmm15 \n" + + "vpunpckldq %%xmm9, %%xmm8, %%xmm0 \n" + "vpunpckldq %%xmm11, %%xmm10, %%xmm1 \n" + "vpunpckhdq %%xmm9, %%xmm8, %%xmm2 \n" + "vpunpckhdq %%xmm11, %%xmm10, %%xmm3 \n" + "vpunpckldq %%xmm13, %%xmm12, %%xmm4 \n" + "vpunpckldq %%xmm15, %%xmm14, %%xmm5 \n" + "vpunpckhdq %%xmm13, %%xmm12, %%xmm6 \n" + "vpunpckhdq %%xmm15, %%xmm14, %%xmm7 \n" + + "vpunpcklqdq %%xmm1, %%xmm0, %%xmm8 \n" + "vpunpckhqdq %%xmm1, %%xmm0, %%xmm9 \n" + "vpunpcklqdq %%xmm3, %%xmm2, %%xmm10 \n" + "vpunpckhqdq %%xmm3, %%xmm2, %%xmm11 \n" + "vpunpcklqdq %%xmm4, %%xmm5, %%xmm12 \n" + "vpunpckhqdq %%xmm5, %%xmm4, %%xmm13 \n" + "vpunpcklqdq %%xmm7, %%xmm6, %%xmm14 \n" + "vpunpckhqdq %%xmm7, %%xmm6, %%xmm15 \n" + + /* Rotate the rows to get the correct final order. + * Rotating xmm12 isn't needed, as we can handle + * the rotation in the PUNPCKLQDQ above. Rotating + * xmm8 isn't needed as it's already in the right order + */ + + "vpalignr $2, %%xmm9, %%xmm9, %%xmm9 \n" + "vpalignr $4, %%xmm10, %%xmm10, %%xmm10 \n" + "vpalignr $6, %%xmm11, %%xmm11, %%xmm11 \n" + "vpalignr $10, %%xmm13, %%xmm13, %%xmm13 \n" + "vpalignr $12, %%xmm14, %%xmm14, %%xmm14 \n" + "vpalignr $14, %%xmm15, %%xmm15, %%xmm15 \n" + + /* Convert from half -> float */ + + "vcvtph2ps %%xmm8, %%ymm8 \n" + "vcvtph2ps %%xmm9, %%ymm9 \n" + "vcvtph2ps %%xmm10, %%ymm10 \n" + "vcvtph2ps %%xmm11, %%ymm11 \n" + "vcvtph2ps %%xmm12, %%ymm12 \n" + "vcvtph2ps %%xmm13, %%ymm13 \n" + "vcvtph2ps %%xmm14, %%ymm14 \n" + "vcvtph2ps %%xmm15, %%ymm15 \n" + + /* Move float values to dst */ + + "vmovaps %%ymm8, (%1) \n" + "vmovaps %%ymm9, 32(%1) \n" + "vmovaps %%ymm10, 64(%1) \n" + "vmovaps %%ymm11, 96(%1) \n" + "vmovaps %%ymm12, 128(%1) \n" + "vmovaps %%ymm13, 160(%1) \n" + "vmovaps %%ymm14, 192(%1) \n" + "vmovaps %%ymm15, 224(%1) \n" + #ifndef __AVX__ + "vzeroupper \n" + #endif /* __AVX__ */ + : /* Output */ + : /* Input */ "r"(src), "r"(dst) + : /* Clobber */ "memory", + #ifndef __AVX__ + "%xmm0", "%xmm1", "%xmm2", "%xmm3", + "%xmm4", "%xmm5", "%xmm6", "%xmm7", + "%xmm8", "%xmm9", "%xmm10", "%xmm11", + "%xmm12", "%xmm13", "%xmm14", "%xmm15" + #else + "%ymm0", "%ymm1", "%ymm2", "%ymm3", + "%ymm4", "%ymm5", "%ymm6", "%ymm7", + "%ymm8", "%ymm9", "%ymm10", "%ymm11", + "%ymm12", "%ymm13", "%ymm14", "%ymm15" + #endif /* __AVX__ */ + ); + + #else + fromHalfZigZag_scalar(src, dst); + #endif /* defined IMF_HAVE_GCC_INLINEASM_64 */ +} + + +// +// Inverse 8x8 DCT, only inverting the DC. This assumes that +// all AC frequencies are 0. +// + +#ifndef IMF_HAVE_SSE2 + +void +dctInverse8x8DcOnly (float *data) +{ + float val = data[0] * 3.535536e-01f * 3.535536e-01f; + + for (int i = 0; i < 64; ++i) + data[i] = val; +} + +#else /* IMF_HAVE_SSE2 */ + +void +dctInverse8x8DcOnly (float *data) +{ + __m128 src = _mm_set1_ps (data[0] * 3.535536e-01f * 3.535536e-01f); + __m128 *dst = (__m128 *)data; + + for (int i = 0; i < 16; ++i) + dst[i] = src; +} + +#endif /* IMF_HAVE_SSE2 */ + + +// +// Full 8x8 Inverse DCT: +// +// Simple inverse DCT on an 8x8 block, with scalar ops only. +// Operates on data in-place. +// +// This is based on the iDCT formuation (y = frequency domain, +// x = spatial domain) +// +// [x0] [ ][y0] [ ][y1] +// [x1] = [ M1 ][y2] + [ M2 ][y3] +// [x2] [ ][y4] [ ][y5] +// [x3] [ ][y6] [ ][y7] +// +// [x7] [ ][y0] [ ][y1] +// [x6] = [ M1 ][y2] - [ M2 ][y3] +// [x5] [ ][y4] [ ][y5] +// [x4] [ ][y6] [ ][y7] +// +// where M1: M2: +// +// [a c a f] [b d e g] +// [a f -a -c] [d -g -b -e] +// [a -f -a c] [e -b g d] +// [a -c a -f] [g -e d -b] +// +// and the constants are as defined below.. +// +// If you know how many of the lower rows are zero, that can +// be passed in to help speed things up. If you don't know, +// just set zeroedRows=0. +// + +// +// Default implementation +// + +template +void +dctInverse8x8_scalar (float *data) +{ + const float a = .5f * cosf (3.14159f / 4.0f); + const float b = .5f * cosf (3.14159f / 16.0f); + const float c = .5f * cosf (3.14159f / 8.0f); + const float d = .5f * cosf (3.f*3.14159f / 16.0f); + const float e = .5f * cosf (5.f*3.14159f / 16.0f); + const float f = .5f * cosf (3.f*3.14159f / 8.0f); + const float g = .5f * cosf (7.f*3.14159f / 16.0f); + + float alpha[4], beta[4], theta[4], gamma[4]; + + float *rowPtr = NULL; + + // + // First pass - row wise. + // + // This looks less-compact than the description above in + // an attempt to fold together common sub-expressions. + // + + for (int row = 0; row < 8 - zeroedRows; ++row) + { + rowPtr = data + row * 8; + + alpha[0] = c * rowPtr[2]; + alpha[1] = f * rowPtr[2]; + alpha[2] = c * rowPtr[6]; + alpha[3] = f * rowPtr[6]; + + beta[0] = b * rowPtr[1] + d * rowPtr[3] + e * rowPtr[5] + g * rowPtr[7]; + beta[1] = d * rowPtr[1] - g * rowPtr[3] - b * rowPtr[5] - e * rowPtr[7]; + beta[2] = e * rowPtr[1] - b * rowPtr[3] + g * rowPtr[5] + d * rowPtr[7]; + beta[3] = g * rowPtr[1] - e * rowPtr[3] + d * rowPtr[5] - b * rowPtr[7]; + + theta[0] = a * (rowPtr[0] + rowPtr[4]); + theta[3] = a * (rowPtr[0] - rowPtr[4]); + + theta[1] = alpha[0] + alpha[3]; + theta[2] = alpha[1] - alpha[2]; + + + gamma[0] = theta[0] + theta[1]; + gamma[1] = theta[3] + theta[2]; + gamma[2] = theta[3] - theta[2]; + gamma[3] = theta[0] - theta[1]; + + + rowPtr[0] = gamma[0] + beta[0]; + rowPtr[1] = gamma[1] + beta[1]; + rowPtr[2] = gamma[2] + beta[2]; + rowPtr[3] = gamma[3] + beta[3]; + + rowPtr[4] = gamma[3] - beta[3]; + rowPtr[5] = gamma[2] - beta[2]; + rowPtr[6] = gamma[1] - beta[1]; + rowPtr[7] = gamma[0] - beta[0]; + } + + // + // Second pass - column wise. + // + + for (int column = 0; column < 8; ++column) + { + alpha[0] = c * data[16+column]; + alpha[1] = f * data[16+column]; + alpha[2] = c * data[48+column]; + alpha[3] = f * data[48+column]; + + beta[0] = b * data[8+column] + d * data[24+column] + + e * data[40+column] + g * data[56+column]; + + beta[1] = d * data[8+column] - g * data[24+column] - + b * data[40+column] - e * data[56+column]; + + beta[2] = e * data[8+column] - b * data[24+column] + + g * data[40+column] + d * data[56+column]; + + beta[3] = g * data[8+column] - e * data[24+column] + + d * data[40+column] - b * data[56+column]; + + theta[0] = a * (data[column] + data[32+column]); + theta[3] = a * (data[column] - data[32+column]); + + theta[1] = alpha[0] + alpha[3]; + theta[2] = alpha[1] - alpha[2]; + + gamma[0] = theta[0] + theta[1]; + gamma[1] = theta[3] + theta[2]; + gamma[2] = theta[3] - theta[2]; + gamma[3] = theta[0] - theta[1]; + + data[ column] = gamma[0] + beta[0]; + data[ 8 + column] = gamma[1] + beta[1]; + data[16 + column] = gamma[2] + beta[2]; + data[24 + column] = gamma[3] + beta[3]; + + data[32 + column] = gamma[3] - beta[3]; + data[40 + column] = gamma[2] - beta[2]; + data[48 + column] = gamma[1] - beta[1]; + data[56 + column] = gamma[0] - beta[0]; + } +} + + +// +// SSE2 Implementation +// + +template +void +dctInverse8x8_sse2 (float *data) +{ + #ifdef IMF_HAVE_SSE2 + __m128 a = {3.535536e-01f,3.535536e-01f,3.535536e-01f,3.535536e-01f}; + __m128 b = {4.903927e-01f,4.903927e-01f,4.903927e-01f,4.903927e-01f}; + __m128 c = {4.619398e-01f,4.619398e-01f,4.619398e-01f,4.619398e-01f}; + __m128 d = {4.157349e-01f,4.157349e-01f,4.157349e-01f,4.157349e-01f}; + __m128 e = {2.777855e-01f,2.777855e-01f,2.777855e-01f,2.777855e-01f}; + __m128 f = {1.913422e-01f,1.913422e-01f,1.913422e-01f,1.913422e-01f}; + __m128 g = {9.754573e-02f,9.754573e-02f,9.754573e-02f,9.754573e-02f}; + + __m128 c0 = {3.535536e-01f, 3.535536e-01f, 3.535536e-01f, 3.535536e-01f}; + __m128 c1 = {4.619398e-01f, 1.913422e-01f,-1.913422e-01f,-4.619398e-01f}; + __m128 c2 = {3.535536e-01f,-3.535536e-01f,-3.535536e-01f, 3.535536e-01f}; + __m128 c3 = {1.913422e-01f,-4.619398e-01f, 4.619398e-01f,-1.913422e-01f}; + + __m128 c4 = {4.903927e-01f, 4.157349e-01f, 2.777855e-01f, 9.754573e-02f}; + __m128 c5 = {4.157349e-01f,-9.754573e-02f,-4.903927e-01f,-2.777855e-01f}; + __m128 c6 = {2.777855e-01f,-4.903927e-01f, 9.754573e-02f, 4.157349e-01f}; + __m128 c7 = {9.754573e-02f,-2.777855e-01f, 4.157349e-01f,-4.903927e-01f}; + + __m128 *srcVec = (__m128 *)data; + __m128 x[8], evenSum, oddSum; + __m128 in[8], alpha[4], beta[4], theta[4], gamma[4]; + + // + // Rows - + // + // Treat this just like matrix-vector multiplication. The + // trick is to note that: + // + // [M00 M01 M02 M03][v0] [(v0 M00) + (v1 M01) + (v2 M02) + (v3 M03)] + // [M10 M11 M12 M13][v1] = [(v0 M10) + (v1 M11) + (v2 M12) + (v3 M13)] + // [M20 M21 M22 M23][v2] [(v0 M20) + (v1 M21) + (v2 M22) + (v3 M23)] + // [M30 M31 M32 M33][v3] [(v0 M30) + (v1 M31) + (v2 M32) + (v3 M33)] + // + // Then, we can fill a register with v_i and multiply by the i-th column + // of M, accumulating across all i-s. + // + // The kids refer to the populating of a register with a single value + // "broadcasting", and it can be done with a shuffle instruction. It + // seems to be the slowest part of the whole ordeal. + // + // Our matrix columns are stored above in c0-c7. c0-3 make up M1, and + // c4-7 are from M2. + // + + #define DCT_INVERSE_8x8_SS2_ROW_LOOP(i) \ + /* \ + * Broadcast the components of the row \ + */ \ + \ + x[0] = _mm_shuffle_ps (srcVec[2 * i], \ + srcVec[2 * i], \ + _MM_SHUFFLE (0, 0, 0, 0)); \ + \ + x[1] = _mm_shuffle_ps (srcVec[2 * i], \ + srcVec[2 * i], \ + _MM_SHUFFLE (1, 1, 1, 1)); \ + \ + x[2] = _mm_shuffle_ps (srcVec[2 * i], \ + srcVec[2 * i], \ + _MM_SHUFFLE (2, 2, 2, 2)); \ + \ + x[3] = _mm_shuffle_ps (srcVec[2 * i], \ + srcVec[2 * i], \ + _MM_SHUFFLE (3, 3, 3, 3)); \ + \ + x[4] = _mm_shuffle_ps (srcVec[2 * i + 1], \ + srcVec[2 * i + 1], \ + _MM_SHUFFLE (0, 0, 0, 0)); \ + \ + x[5] = _mm_shuffle_ps (srcVec[2 * i + 1], \ + srcVec[2 * i + 1], \ + _MM_SHUFFLE (1, 1, 1, 1)); \ + \ + x[6] = _mm_shuffle_ps (srcVec[2 * i + 1], \ + srcVec[2 * i + 1], \ + _MM_SHUFFLE (2, 2, 2, 2)); \ + \ + x[7] = _mm_shuffle_ps (srcVec[2 * i + 1], \ + srcVec[2 * i + 1], \ + _MM_SHUFFLE (3, 3, 3, 3)); \ + /* \ + * Multiply the components by each column of the matrix \ + */ \ + \ + x[0] = _mm_mul_ps (x[0], c0); \ + x[2] = _mm_mul_ps (x[2], c1); \ + x[4] = _mm_mul_ps (x[4], c2); \ + x[6] = _mm_mul_ps (x[6], c3); \ + \ + x[1] = _mm_mul_ps (x[1], c4); \ + x[3] = _mm_mul_ps (x[3], c5); \ + x[5] = _mm_mul_ps (x[5], c6); \ + x[7] = _mm_mul_ps (x[7], c7); \ + \ + /* \ + * Add across \ + */ \ + \ + evenSum = _mm_setzero_ps(); \ + evenSum = _mm_add_ps (evenSum, x[0]); \ + evenSum = _mm_add_ps (evenSum, x[2]); \ + evenSum = _mm_add_ps (evenSum, x[4]); \ + evenSum = _mm_add_ps (evenSum, x[6]); \ + \ + oddSum = _mm_setzero_ps(); \ + oddSum = _mm_add_ps (oddSum, x[1]); \ + oddSum = _mm_add_ps (oddSum, x[3]); \ + oddSum = _mm_add_ps (oddSum, x[5]); \ + oddSum = _mm_add_ps (oddSum, x[7]); \ + \ + /* \ + * Final Sum: \ + * out [0, 1, 2, 3] = evenSum + oddSum \ + * out [7, 6, 5, 4] = evenSum - oddSum \ + */ \ + \ + srcVec[2 * i] = _mm_add_ps (evenSum, oddSum); \ + srcVec[2 * i + 1] = _mm_sub_ps (evenSum, oddSum); \ + srcVec[2 * i + 1] = _mm_shuffle_ps (srcVec[2 * i + 1], \ + srcVec[2 * i + 1], \ + _MM_SHUFFLE (0, 1, 2, 3)); + + switch (zeroedRows) + { + case 0: + default: + DCT_INVERSE_8x8_SS2_ROW_LOOP (0) + DCT_INVERSE_8x8_SS2_ROW_LOOP (1) + DCT_INVERSE_8x8_SS2_ROW_LOOP (2) + DCT_INVERSE_8x8_SS2_ROW_LOOP (3) + DCT_INVERSE_8x8_SS2_ROW_LOOP (4) + DCT_INVERSE_8x8_SS2_ROW_LOOP (5) + DCT_INVERSE_8x8_SS2_ROW_LOOP (6) + DCT_INVERSE_8x8_SS2_ROW_LOOP (7) + break; + + case 1: + DCT_INVERSE_8x8_SS2_ROW_LOOP (0) + DCT_INVERSE_8x8_SS2_ROW_LOOP (1) + DCT_INVERSE_8x8_SS2_ROW_LOOP (2) + DCT_INVERSE_8x8_SS2_ROW_LOOP (3) + DCT_INVERSE_8x8_SS2_ROW_LOOP (4) + DCT_INVERSE_8x8_SS2_ROW_LOOP (5) + DCT_INVERSE_8x8_SS2_ROW_LOOP (6) + break; + + case 2: + DCT_INVERSE_8x8_SS2_ROW_LOOP (0) + DCT_INVERSE_8x8_SS2_ROW_LOOP (1) + DCT_INVERSE_8x8_SS2_ROW_LOOP (2) + DCT_INVERSE_8x8_SS2_ROW_LOOP (3) + DCT_INVERSE_8x8_SS2_ROW_LOOP (4) + DCT_INVERSE_8x8_SS2_ROW_LOOP (5) + break; + + case 3: + DCT_INVERSE_8x8_SS2_ROW_LOOP (0) + DCT_INVERSE_8x8_SS2_ROW_LOOP (1) + DCT_INVERSE_8x8_SS2_ROW_LOOP (2) + DCT_INVERSE_8x8_SS2_ROW_LOOP (3) + DCT_INVERSE_8x8_SS2_ROW_LOOP (4) + break; + + case 4: + DCT_INVERSE_8x8_SS2_ROW_LOOP (0) + DCT_INVERSE_8x8_SS2_ROW_LOOP (1) + DCT_INVERSE_8x8_SS2_ROW_LOOP (2) + DCT_INVERSE_8x8_SS2_ROW_LOOP (3) + break; + + case 5: + DCT_INVERSE_8x8_SS2_ROW_LOOP (0) + DCT_INVERSE_8x8_SS2_ROW_LOOP (1) + DCT_INVERSE_8x8_SS2_ROW_LOOP (2) + break; + + case 6: + DCT_INVERSE_8x8_SS2_ROW_LOOP (0) + DCT_INVERSE_8x8_SS2_ROW_LOOP (1) + break; + + case 7: + DCT_INVERSE_8x8_SS2_ROW_LOOP (0) + break; + } + + // + // Columns - + // + // This is slightly more straightforward, if less readable. Here + // we just operate on 4 columns at a time, in two batches. + // + // The slight mess is to try and cache sub-expressions, which + // we ignore in the row-wise pass. + // + + for (int col = 0; col < 2; ++col) + { + + for (int i = 0; i < 8; ++i) + in[i] = srcVec[2 * i + col]; + + alpha[0] = _mm_mul_ps (c, in[2]); + alpha[1] = _mm_mul_ps (f, in[2]); + alpha[2] = _mm_mul_ps (c, in[6]); + alpha[3] = _mm_mul_ps (f, in[6]); + + beta[0] = _mm_add_ps (_mm_add_ps (_mm_mul_ps (in[1], b), + _mm_mul_ps (in[3], d)), + _mm_add_ps (_mm_mul_ps (in[5], e), + _mm_mul_ps (in[7], g))); + + beta[1] = _mm_sub_ps (_mm_sub_ps (_mm_mul_ps (in[1], d), + _mm_mul_ps (in[3], g)), + _mm_add_ps (_mm_mul_ps (in[5], b), + _mm_mul_ps (in[7], e))); + + beta[2] = _mm_add_ps (_mm_sub_ps (_mm_mul_ps (in[1], e), + _mm_mul_ps (in[3], b)), + _mm_add_ps (_mm_mul_ps (in[5], g), + _mm_mul_ps (in[7], d))); + + beta[3] = _mm_add_ps (_mm_sub_ps (_mm_mul_ps (in[1], g), + _mm_mul_ps (in[3], e)), + _mm_sub_ps (_mm_mul_ps (in[5], d), + _mm_mul_ps (in[7], b))); + + theta[0] = _mm_mul_ps (a, _mm_add_ps (in[0], in[4])); + theta[3] = _mm_mul_ps (a, _mm_sub_ps (in[0], in[4])); + + theta[1] = _mm_add_ps (alpha[0], alpha[3]); + theta[2] = _mm_sub_ps (alpha[1], alpha[2]); + + gamma[0] = _mm_add_ps (theta[0], theta[1]); + gamma[1] = _mm_add_ps (theta[3], theta[2]); + gamma[2] = _mm_sub_ps (theta[3], theta[2]); + gamma[3] = _mm_sub_ps (theta[0], theta[1]); + + srcVec[ col] = _mm_add_ps (gamma[0], beta[0]); + srcVec[2+col] = _mm_add_ps (gamma[1], beta[1]); + srcVec[4+col] = _mm_add_ps (gamma[2], beta[2]); + srcVec[6+col] = _mm_add_ps (gamma[3], beta[3]); + + srcVec[ 8+col] = _mm_sub_ps (gamma[3], beta[3]); + srcVec[10+col] = _mm_sub_ps (gamma[2], beta[2]); + srcVec[12+col] = _mm_sub_ps (gamma[1], beta[1]); + srcVec[14+col] = _mm_sub_ps (gamma[0], beta[0]); + } + + #else /* IMF_HAVE_SSE2 */ + + dctInverse8x8_scalar (data); + + #endif /* IMF_HAVE_SSE2 */ +} + + +// +// AVX Implementation +// + +#define STR(A) #A + +#define IDCT_AVX_SETUP_2_ROWS(_DST0, _DST1, _TMP0, _TMP1, \ + _OFF00, _OFF01, _OFF10, _OFF11) \ + "vmovaps " STR(_OFF00) "(%0), %%xmm" STR(_TMP0) " \n" \ + "vmovaps " STR(_OFF01) "(%0), %%xmm" STR(_TMP1) " \n" \ + " \n" \ + "vinsertf128 $1, " STR(_OFF10) "(%0), %%ymm" STR(_TMP0) ", %%ymm" STR(_TMP0) " \n" \ + "vinsertf128 $1, " STR(_OFF11) "(%0), %%ymm" STR(_TMP1) ", %%ymm" STR(_TMP1) " \n" \ + " \n" \ + "vunpcklpd %%ymm" STR(_TMP1) ", %%ymm" STR(_TMP0) ", %%ymm" STR(_DST0) " \n" \ + "vunpckhpd %%ymm" STR(_TMP1) ", %%ymm" STR(_TMP0) ", %%ymm" STR(_DST1) " \n" \ + " \n" \ + "vunpcklps %%ymm" STR(_DST1) ", %%ymm" STR(_DST0) ", %%ymm" STR(_TMP0) " \n" \ + "vunpckhps %%ymm" STR(_DST1) ", %%ymm" STR(_DST0) ", %%ymm" STR(_TMP1) " \n" \ + " \n" \ + "vunpcklpd %%ymm" STR(_TMP1) ", %%ymm" STR(_TMP0) ", %%ymm" STR(_DST0) " \n" \ + "vunpckhpd %%ymm" STR(_TMP1) ", %%ymm" STR(_TMP0) ", %%ymm" STR(_DST1) " \n" + +#define IDCT_AVX_MMULT_ROWS(_SRC) \ + /* Broadcast the source values into y12-y15 */ \ + "vpermilps $0x00, " STR(_SRC) ", %%ymm12 \n" \ + "vpermilps $0x55, " STR(_SRC) ", %%ymm13 \n" \ + "vpermilps $0xaa, " STR(_SRC) ", %%ymm14 \n" \ + "vpermilps $0xff, " STR(_SRC) ", %%ymm15 \n" \ + \ + /* Multiple coefs and the broadcasted values */ \ + "vmulps %%ymm12, %%ymm8, %%ymm12 \n" \ + "vmulps %%ymm13, %%ymm9, %%ymm13 \n" \ + "vmulps %%ymm14, %%ymm10, %%ymm14 \n" \ + "vmulps %%ymm15, %%ymm11, %%ymm15 \n" \ + \ + /* Accumulate the result back into the source */ \ + "vaddps %%ymm13, %%ymm12, %%ymm12 \n" \ + "vaddps %%ymm15, %%ymm14, %%ymm14 \n" \ + "vaddps %%ymm14, %%ymm12, " STR(_SRC) "\n" + +#define IDCT_AVX_EO_TO_ROW_HALVES(_EVEN, _ODD, _FRONT, _BACK) \ + "vsubps " STR(_ODD) "," STR(_EVEN) "," STR(_BACK) "\n" \ + "vaddps " STR(_ODD) "," STR(_EVEN) "," STR(_FRONT) "\n" \ + /* Reverse the back half */ \ + "vpermilps $0x1b," STR(_BACK) "," STR(_BACK) "\n" + +/* In order to allow for path paths when we know certain rows + * of the 8x8 block are zero, most of the body of the DCT is + * in the following macro. Statements are wrapped in a ROWn() + * macro, where n is the lowest row in the 8x8 block in which + * they depend. + * + * This should work for the cases where we have 2-8 full rows. + * the 1-row case is special, and we'll handle it seperately. + */ +#define IDCT_AVX_BODY \ + /* ============================================== + * Row 1D DCT + * ---------------------------------------------- + */ \ + \ + /* Setup for the row-oriented 1D DCT. Assuming that (%0) holds + * the row-major 8x8 block, load ymm0-3 with the even columns + * and ymm4-7 with the odd columns. The lower half of the ymm + * holds one row, while the upper half holds the next row. + * + * If our source is: + * a0 a1 a2 a3 a4 a5 a6 a7 + * b0 b1 b2 b3 b4 b5 b6 b7 + * + * We'll be forming: + * a0 a2 a4 a6 b0 b2 b4 b6 + * a1 a3 a5 a7 b1 b3 b5 b7 + */ \ + ROW0( IDCT_AVX_SETUP_2_ROWS(0, 4, 14, 15, 0, 16, 32, 48) ) \ + ROW2( IDCT_AVX_SETUP_2_ROWS(1, 5, 12, 13, 64, 80, 96, 112) ) \ + ROW4( IDCT_AVX_SETUP_2_ROWS(2, 6, 10, 11, 128, 144, 160, 176) ) \ + ROW6( IDCT_AVX_SETUP_2_ROWS(3, 7, 8, 9, 192, 208, 224, 240) ) \ + \ + /* Multiple the even columns (ymm0-3) by the matrix M1 + * storing the results back in ymm0-3 + * + * Assume that (%1) holds the matrix in column major order + */ \ + "vbroadcastf128 (%1), %%ymm8 \n" \ + "vbroadcastf128 16(%1), %%ymm9 \n" \ + "vbroadcastf128 32(%1), %%ymm10 \n" \ + "vbroadcastf128 48(%1), %%ymm11 \n" \ + \ + ROW0( IDCT_AVX_MMULT_ROWS(%%ymm0) ) \ + ROW2( IDCT_AVX_MMULT_ROWS(%%ymm1) ) \ + ROW4( IDCT_AVX_MMULT_ROWS(%%ymm2) ) \ + ROW6( IDCT_AVX_MMULT_ROWS(%%ymm3) ) \ + \ + /* Repeat, but with the odd columns (ymm4-7) and the + * matrix M2 + */ \ + "vbroadcastf128 64(%1), %%ymm8 \n" \ + "vbroadcastf128 80(%1), %%ymm9 \n" \ + "vbroadcastf128 96(%1), %%ymm10 \n" \ + "vbroadcastf128 112(%1), %%ymm11 \n" \ + \ + ROW0( IDCT_AVX_MMULT_ROWS(%%ymm4) ) \ + ROW2( IDCT_AVX_MMULT_ROWS(%%ymm5) ) \ + ROW4( IDCT_AVX_MMULT_ROWS(%%ymm6) ) \ + ROW6( IDCT_AVX_MMULT_ROWS(%%ymm7) ) \ + \ + /* Sum the M1 (ymm0-3) and M2 (ymm4-7) results to get the + * front halves of the results, and difference to get the + * back halves. The front halfs end up in ymm0-3, the back + * halves end up in ymm12-15. + */ \ + ROW0( IDCT_AVX_EO_TO_ROW_HALVES(%%ymm0, %%ymm4, %%ymm0, %%ymm12) ) \ + ROW2( IDCT_AVX_EO_TO_ROW_HALVES(%%ymm1, %%ymm5, %%ymm1, %%ymm13) ) \ + ROW4( IDCT_AVX_EO_TO_ROW_HALVES(%%ymm2, %%ymm6, %%ymm2, %%ymm14) ) \ + ROW6( IDCT_AVX_EO_TO_ROW_HALVES(%%ymm3, %%ymm7, %%ymm3, %%ymm15) ) \ + \ + /* Reassemble the rows halves into ymm0-7 */ \ + ROW7( "vperm2f128 $0x13, %%ymm3, %%ymm15, %%ymm7 \n" ) \ + ROW6( "vperm2f128 $0x02, %%ymm3, %%ymm15, %%ymm6 \n" ) \ + ROW5( "vperm2f128 $0x13, %%ymm2, %%ymm14, %%ymm5 \n" ) \ + ROW4( "vperm2f128 $0x02, %%ymm2, %%ymm14, %%ymm4 \n" ) \ + ROW3( "vperm2f128 $0x13, %%ymm1, %%ymm13, %%ymm3 \n" ) \ + ROW2( "vperm2f128 $0x02, %%ymm1, %%ymm13, %%ymm2 \n" ) \ + ROW1( "vperm2f128 $0x13, %%ymm0, %%ymm12, %%ymm1 \n" ) \ + ROW0( "vperm2f128 $0x02, %%ymm0, %%ymm12, %%ymm0 \n" ) \ + \ + \ + /* ============================================== + * Column 1D DCT + * ---------------------------------------------- + */ \ + \ + /* Rows should be in ymm0-7, and M2 columns should still be + * preserved in ymm8-11. M2 has 4 unique values (and +- + * versions of each), and all (positive) values appear in + * the first column (and row), which is in ymm8. + * + * For the column-wise DCT, we need to: + * 1) Broadcast each element a row of M2 into 4 vectors + * 2) Multiple the odd rows (ymm1,3,5,7) by the broadcasts. + * 3) Accumulate into ymm12-15 for the odd outputs. + * + * Instead of doing 16 broadcasts for each element in M2, + * do 4, filling y8-11 with: + * + * ymm8: [ b b b b | b b b b ] + * ymm9: [ d d d d | d d d d ] + * ymm10: [ e e e e | e e e e ] + * ymm11: [ g g g g | g g g g ] + * + * And deal with the negative values by subtracting during accum. + */ \ + "vpermilps $0xff, %%ymm8, %%ymm11 \n" \ + "vpermilps $0xaa, %%ymm8, %%ymm10 \n" \ + "vpermilps $0x55, %%ymm8, %%ymm9 \n" \ + "vpermilps $0x00, %%ymm8, %%ymm8 \n" \ + \ + /* This one is easy, since we have ymm12-15 open for scratch + * ymm12 = b ymm1 + d ymm3 + e ymm5 + g ymm7 + */ \ + ROW1( "vmulps %%ymm1, %%ymm8, %%ymm12 \n" ) \ + ROW3( "vmulps %%ymm3, %%ymm9, %%ymm13 \n" ) \ + ROW5( "vmulps %%ymm5, %%ymm10, %%ymm14 \n" ) \ + ROW7( "vmulps %%ymm7, %%ymm11, %%ymm15 \n" ) \ + \ + ROW3( "vaddps %%ymm12, %%ymm13, %%ymm12 \n" ) \ + ROW7( "vaddps %%ymm14, %%ymm15, %%ymm14 \n" ) \ + ROW5( "vaddps %%ymm12, %%ymm14, %%ymm12 \n" ) \ + \ + /* Tricker, since only y13-15 are open for scratch + * ymm13 = d ymm1 - g ymm3 - b ymm5 - e ymm7 + */ \ + ROW1( "vmulps %%ymm1, %%ymm9, %%ymm13 \n" ) \ + ROW3( "vmulps %%ymm3, %%ymm11, %%ymm14 \n" ) \ + ROW5( "vmulps %%ymm5, %%ymm8, %%ymm15 \n" ) \ + \ + ROW5( "vaddps %%ymm14, %%ymm15, %%ymm14 \n" ) \ + ROW3( "vsubps %%ymm14, %%ymm13, %%ymm13 \n" ) \ + \ + ROW7( "vmulps %%ymm7, %%ymm10, %%ymm15 \n" ) \ + ROW7( "vsubps %%ymm15, %%ymm13, %%ymm13 \n" ) \ + \ + /* Tricker still, as only y14-15 are open for scratch + * ymm14 = e ymm1 - b ymm3 + g ymm5 + d ymm7 + */ \ + ROW1( "vmulps %%ymm1, %%ymm10, %%ymm14 \n" ) \ + ROW3( "vmulps %%ymm3, %%ymm8, %%ymm15 \n" ) \ + \ + ROW3( "vsubps %%ymm15, %%ymm14, %%ymm14 \n" ) \ + \ + ROW5( "vmulps %%ymm5, %%ymm11, %%ymm15 \n" ) \ + ROW5( "vaddps %%ymm15, %%ymm14, %%ymm14 \n" ) \ + \ + ROW7( "vmulps %%ymm7, %%ymm9, %%ymm15 \n" ) \ + ROW7( "vaddps %%ymm15, %%ymm14, %%ymm14 \n" ) \ + \ + \ + /* Easy, as we can blow away ymm1,3,5,7 for scratch + * ymm15 = g ymm1 - e ymm3 + d ymm5 - b ymm7 + */ \ + ROW1( "vmulps %%ymm1, %%ymm11, %%ymm15 \n" ) \ + ROW3( "vmulps %%ymm3, %%ymm10, %%ymm3 \n" ) \ + ROW5( "vmulps %%ymm5, %%ymm9, %%ymm5 \n" ) \ + ROW7( "vmulps %%ymm7, %%ymm8, %%ymm7 \n" ) \ + \ + ROW5( "vaddps %%ymm15, %%ymm5, %%ymm15 \n" ) \ + ROW7( "vaddps %%ymm3, %%ymm7, %%ymm3 \n" ) \ + ROW3( "vsubps %%ymm3, %%ymm15, %%ymm15 \n" ) \ + \ + \ + /* Load coefs for M1. Because we're going to broadcast + * coefs, we don't need to load the actual structure from + * M1. Instead, just load enough that we can broadcast. + * There are only 6 unique values in M1, but they're in +- + * pairs, leaving only 3 unique coefs if we add and subtract + * properly. + * + * Fill ymm1 with coef[2] = [ a a c f | a a c f ] + * Broadcast ymm5 with [ f f f f | f f f f ] + * Broadcast ymm3 with [ c c c c | c c c c ] + * Broadcast ymm1 with [ a a a a | a a a a ] + */ \ + "vbroadcastf128 8(%1), %%ymm1 \n" \ + "vpermilps $0xff, %%ymm1, %%ymm5 \n" \ + "vpermilps $0xaa, %%ymm1, %%ymm3 \n" \ + "vpermilps $0x00, %%ymm1, %%ymm1 \n" \ + \ + /* If we expand E = [M1] [x0 x2 x4 x6]^t, we get the following + * common expressions: + * + * E_0 = ymm8 = (a ymm0 + a ymm4) + (c ymm2 + f ymm6) + * E_3 = ymm11 = (a ymm0 + a ymm4) - (c ymm2 + f ymm6) + * + * E_1 = ymm9 = (a ymm0 - a ymm4) + (f ymm2 - c ymm6) + * E_2 = ymm10 = (a ymm0 - a ymm4) - (f ymm2 - c ymm6) + * + * Afterwards, ymm8-11 will hold the even outputs. + */ \ + \ + /* ymm11 = (a ymm0 + a ymm4), ymm1 = (a ymm0 - a ymm4) */ \ + ROW0( "vmulps %%ymm1, %%ymm0, %%ymm11 \n" ) \ + ROW4( "vmulps %%ymm1, %%ymm4, %%ymm4 \n" ) \ + ROW0( "vmovaps %%ymm11, %%ymm1 \n" ) \ + ROW4( "vaddps %%ymm4, %%ymm11, %%ymm11 \n" ) \ + ROW4( "vsubps %%ymm4, %%ymm1, %%ymm1 \n" ) \ + \ + /* ymm7 = (c ymm2 + f ymm6) */ \ + ROW2( "vmulps %%ymm3, %%ymm2, %%ymm7 \n" ) \ + ROW6( "vmulps %%ymm5, %%ymm6, %%ymm9 \n" ) \ + ROW6( "vaddps %%ymm9, %%ymm7, %%ymm7 \n" ) \ + \ + /* E_0 = ymm8 = (a ymm0 + a ymm4) + (c ymm2 + f ymm6) + * E_3 = ymm11 = (a ymm0 + a ymm4) - (c ymm2 + f ymm6) + */ \ + ROW0( "vmovaps %%ymm11, %%ymm8 \n" ) \ + ROW2( "vaddps %%ymm7, %%ymm8, %%ymm8 \n" ) \ + ROW2( "vsubps %%ymm7, %%ymm11, %%ymm11 \n" ) \ + \ + /* ymm7 = (f ymm2 - c ymm6) */ \ + ROW2( "vmulps %%ymm5, %%ymm2, %%ymm7 \n" ) \ + ROW6( "vmulps %%ymm3, %%ymm6, %%ymm9 \n" ) \ + ROW6( "vsubps %%ymm9, %%ymm7, %%ymm7 \n" ) \ + \ + /* E_1 = ymm9 = (a ymm0 - a ymm4) + (f ymm2 - c ymm6) + * E_2 = ymm10 = (a ymm0 - a ymm4) - (f ymm2 - c ymm6) + */ \ + ROW0( "vmovaps %%ymm1, %%ymm9 \n" ) \ + ROW0( "vmovaps %%ymm1, %%ymm10 \n" ) \ + ROW2( "vaddps %%ymm7, %%ymm1, %%ymm9 \n" ) \ + ROW2( "vsubps %%ymm7, %%ymm1, %%ymm10 \n" ) \ + \ + /* Add the even (ymm8-11) and the odds (ymm12-15), + * placing the results into ymm0-7 + */ \ + "vaddps %%ymm12, %%ymm8, %%ymm0 \n" \ + "vaddps %%ymm13, %%ymm9, %%ymm1 \n" \ + "vaddps %%ymm14, %%ymm10, %%ymm2 \n" \ + "vaddps %%ymm15, %%ymm11, %%ymm3 \n" \ + \ + "vsubps %%ymm12, %%ymm8, %%ymm7 \n" \ + "vsubps %%ymm13, %%ymm9, %%ymm6 \n" \ + "vsubps %%ymm14, %%ymm10, %%ymm5 \n" \ + "vsubps %%ymm15, %%ymm11, %%ymm4 \n" \ + \ + /* Copy out the results from ymm0-7 */ \ + "vmovaps %%ymm0, (%0) \n" \ + "vmovaps %%ymm1, 32(%0) \n" \ + "vmovaps %%ymm2, 64(%0) \n" \ + "vmovaps %%ymm3, 96(%0) \n" \ + "vmovaps %%ymm4, 128(%0) \n" \ + "vmovaps %%ymm5, 160(%0) \n" \ + "vmovaps %%ymm6, 192(%0) \n" \ + "vmovaps %%ymm7, 224(%0) \n" + +/* Output, input, and clobber (OIC) sections of the inline asm */ +#define IDCT_AVX_OIC(_IN0) \ + : /* Output */ \ + : /* Input */ "r"(_IN0), "r"(sAvxCoef) \ + : /* Clobber */ "memory", \ + "%xmm0", "%xmm1", "%xmm2", "%xmm3", \ + "%xmm4", "%xmm5", "%xmm6", "%xmm7", \ + "%xmm8", "%xmm9", "%xmm10", "%xmm11",\ + "%xmm12", "%xmm13", "%xmm14", "%xmm15" + +/* Include vzeroupper for non-AVX builds */ +#ifndef __AVX__ + #define IDCT_AVX_ASM(_IN0) \ + __asm__( \ + IDCT_AVX_BODY \ + "vzeroupper \n" \ + IDCT_AVX_OIC(_IN0) \ + ); +#else /* __AVX__ */ + #define IDCT_AVX_ASM(_IN0) \ + __asm__( \ + IDCT_AVX_BODY \ + IDCT_AVX_OIC(_IN0) \ + ); +#endif /* __AVX__ */ + +template +void +dctInverse8x8_avx (float *data) +{ + #if defined IMF_HAVE_GCC_INLINEASM_64 + + /* The column-major version of M1, followed by the + * column-major version of M2: + * + * [ a c a f ] [ b d e g ] + * M1 = [ a f -a -c ] M2 = [ d -g -b -e ] + * [ a -f -a c ] [ e -b g d ] + * [ a -c a -f ] [ g -e d -b ] + */ + const float sAvxCoef[32] __attribute__((aligned(32))) = { + 3.535536e-01, 3.535536e-01, 3.535536e-01, 3.535536e-01, /* a a a a */ + 4.619398e-01, 1.913422e-01, -1.913422e-01, -4.619398e-01, /* c f -f -c */ + 3.535536e-01, -3.535536e-01, -3.535536e-01, 3.535536e-01, /* a -a -a a */ + 1.913422e-01, -4.619398e-01, 4.619398e-01, -1.913422e-01, /* f -c c -f */ + + 4.903927e-01, 4.157349e-01, 2.777855e-01, 9.754573e-02, /* b d e g */ + 4.157349e-01, -9.754573e-02, -4.903927e-01, -2.777855e-01, /* d -g -b -e */ + 2.777855e-01, -4.903927e-01, 9.754573e-02, 4.157349e-01, /* e -b g d */ + 9.754573e-02, -2.777855e-01, 4.157349e-01, -4.903927e-01 /* g -e d -b */ + }; + + #define ROW0(_X) _X + #define ROW1(_X) _X + #define ROW2(_X) _X + #define ROW3(_X) _X + #define ROW4(_X) _X + #define ROW5(_X) _X + #define ROW6(_X) _X + #define ROW7(_X) _X + + if (zeroedRows == 0) { + + IDCT_AVX_ASM(data) + + } else if (zeroedRows == 1) { + + #undef ROW7 + #define ROW7(_X) + IDCT_AVX_ASM(data) + + } else if (zeroedRows == 2) { + + #undef ROW6 + #define ROW6(_X) + IDCT_AVX_ASM(data) + + } else if (zeroedRows == 3) { + + #undef ROW5 + #define ROW5(_X) + IDCT_AVX_ASM(data) + + } else if (zeroedRows == 4) { + + #undef ROW4 + #define ROW4(_X) + IDCT_AVX_ASM(data) + + } else if (zeroedRows == 5) { + + #undef ROW3 + #define ROW3(_X) + IDCT_AVX_ASM(data) + + } else if (zeroedRows == 6) { + + #undef ROW2 + #define ROW2(_X) + IDCT_AVX_ASM(data) + + } else if (zeroedRows == 7) { + + __asm__( + + /* ============================================== + * Row 1D DCT + * ---------------------------------------------- + */ + IDCT_AVX_SETUP_2_ROWS(0, 4, 14, 15, 0, 16, 32, 48) + + "vbroadcastf128 (%1), %%ymm8 \n" + "vbroadcastf128 16(%1), %%ymm9 \n" + "vbroadcastf128 32(%1), %%ymm10 \n" + "vbroadcastf128 48(%1), %%ymm11 \n" + + /* Stash a vector of [a a a a | a a a a] away in ymm2 */ + "vinsertf128 $1, %%xmm8, %%ymm8, %%ymm2 \n" + + IDCT_AVX_MMULT_ROWS(%%ymm0) + + "vbroadcastf128 64(%1), %%ymm8 \n" + "vbroadcastf128 80(%1), %%ymm9 \n" + "vbroadcastf128 96(%1), %%ymm10 \n" + "vbroadcastf128 112(%1), %%ymm11 \n" + + IDCT_AVX_MMULT_ROWS(%%ymm4) + + IDCT_AVX_EO_TO_ROW_HALVES(%%ymm0, %%ymm4, %%ymm0, %%ymm12) + + "vperm2f128 $0x02, %%ymm0, %%ymm12, %%ymm0 \n" + + /* ============================================== + * Column 1D DCT + * ---------------------------------------------- + */ + + /* DC only, so multiple by a and we're done */ + "vmulps %%ymm2, %%ymm0, %%ymm0 \n" + + /* Copy out results */ + "vmovaps %%ymm0, (%0) \n" + "vmovaps %%ymm0, 32(%0) \n" + "vmovaps %%ymm0, 64(%0) \n" + "vmovaps %%ymm0, 96(%0) \n" + "vmovaps %%ymm0, 128(%0) \n" + "vmovaps %%ymm0, 160(%0) \n" + "vmovaps %%ymm0, 192(%0) \n" + "vmovaps %%ymm0, 224(%0) \n" + + #ifndef __AVX__ + "vzeroupper \n" + #endif /* __AVX__ */ + IDCT_AVX_OIC(data) + ); + } else { + assert(false); // Invalid template instance parameter + } + #else /* IMF_HAVE_GCC_INLINEASM_64 */ + + dctInverse8x8_scalar(data); + + #endif /* IMF_HAVE_GCC_INLINEASM_64 */ +} + + +// +// Full 8x8 Forward DCT: +// +// Base forward 8x8 DCT implementation. Works on the data in-place +// +// The implementation describedin Pennebaker + Mitchell, +// section 4.3.2, and illustrated in figure 4-7 +// +// The basic idea is that the 1D DCT math reduces to: +// +// 2*out_0 = c_4 [(s_07 + s_34) + (s_12 + s_56)] +// 2*out_4 = c_4 [(s_07 + s_34) - (s_12 + s_56)] +// +// {2*out_2, 2*out_6} = rot_6 ((d_12 - d_56), (s_07 - s_34)) +// +// {2*out_3, 2*out_5} = rot_-3 (d_07 - c_4 (s_12 - s_56), +// d_34 - c_4 (d_12 + d_56)) +// +// {2*out_1, 2*out_7} = rot_-1 (d_07 + c_4 (s_12 - s_56), +// -d_34 - c_4 (d_12 + d_56)) +// +// where: +// +// c_i = cos(i*pi/16) +// s_i = sin(i*pi/16) +// +// s_ij = in_i + in_j +// d_ij = in_i - in_j +// +// rot_i(x, y) = {c_i*x + s_i*y, -s_i*x + c_i*y} +// +// We'll run the DCT in two passes. First, run the 1D DCT on +// the rows, in-place. Then, run over the columns in-place, +// and be done with it. +// + +#ifndef IMF_HAVE_SSE2 + +// +// Default implementation +// + +void +dctForward8x8 (float *data) +{ + float A0, A1, A2, A3, A4, A5, A6, A7; + float K0, K1, rot_x, rot_y; + + float *srcPtr = data; + float *dstPtr = data; + + const float c1 = cosf (3.14159f * 1.0f / 16.0f); + const float c2 = cosf (3.14159f * 2.0f / 16.0f); + const float c3 = cosf (3.14159f * 3.0f / 16.0f); + const float c4 = cosf (3.14159f * 4.0f / 16.0f); + const float c5 = cosf (3.14159f * 5.0f / 16.0f); + const float c6 = cosf (3.14159f * 6.0f / 16.0f); + const float c7 = cosf (3.14159f * 7.0f / 16.0f); + + const float c1Half = .5f * c1; + const float c2Half = .5f * c2; + const float c3Half = .5f * c3; + const float c5Half = .5f * c5; + const float c6Half = .5f * c6; + const float c7Half = .5f * c7; + + // + // First pass - do a 1D DCT over the rows and write the + // results back in place + // + + for (int row=0; row<8; ++row) + { + float *srcRowPtr = srcPtr + 8 * row; + float *dstRowPtr = dstPtr + 8 * row; + + A0 = srcRowPtr[0] + srcRowPtr[7]; + A1 = srcRowPtr[1] + srcRowPtr[2]; + A2 = srcRowPtr[1] - srcRowPtr[2]; + A3 = srcRowPtr[3] + srcRowPtr[4]; + A4 = srcRowPtr[3] - srcRowPtr[4]; + A5 = srcRowPtr[5] + srcRowPtr[6]; + A6 = srcRowPtr[5] - srcRowPtr[6]; + A7 = srcRowPtr[0] - srcRowPtr[7]; + + K0 = c4 * (A0 + A3); + K1 = c4 * (A1 + A5); + + dstRowPtr[0] = .5f * (K0 + K1); + dstRowPtr[4] = .5f * (K0 - K1); + + // + // (2*dst2, 2*dst6) = rot 6 (d12 - d56, s07 - s34) + // + + rot_x = A2 - A6; + rot_y = A0 - A3; + + dstRowPtr[2] = c6Half * rot_x + c2Half * rot_y; + dstRowPtr[6] = c6Half * rot_y - c2Half * rot_x; + + // + // K0, K1 are active until after dst[1],dst[7] + // as well as dst[3], dst[5] are computed. + // + + K0 = c4 * (A1 - A5); + K1 = -1 * c4 * (A2 + A6); + + // + // Two ways to do a rotation: + // + // rot i (x, y) = + // X = c_i*x + s_i*y + // Y = -s_i*x + c_i*y + // + // OR + // + // X = c_i*(x+y) + (s_i-c_i)*y + // Y = c_i*y - (s_i+c_i)*x + // + // the first case has 4 multiplies, but fewer constants, + // while the 2nd case has fewer multiplies but takes more space. + + // + // (2*dst3, 2*dst5) = rot -3 ( d07 - K0, d34 + K1 ) + // + + rot_x = A7 - K0; + rot_y = A4 + K1; + + dstRowPtr[3] = c3Half * rot_x - c5Half * rot_y; + dstRowPtr[5] = c5Half * rot_x + c3Half * rot_y; + + // + // (2*dst1, 2*dst7) = rot -1 ( d07 + K0, K1 - d34 ) + // + + rot_x = A7 + K0; + rot_y = K1 - A4; + + // + // A: 4, 7 are inactive. All A's are inactive + // + + dstRowPtr[1] = c1Half * rot_x - c7Half * rot_y; + dstRowPtr[7] = c7Half * rot_x + c1Half * rot_y; + } + + // + // Second pass - do the same, but on the columns + // + + for (int column = 0; column < 8; ++column) + { + + A0 = srcPtr[ column] + srcPtr[56 + column]; + A7 = srcPtr[ column] - srcPtr[56 + column]; + + A1 = srcPtr[ 8 + column] + srcPtr[16 + column]; + A2 = srcPtr[ 8 + column] - srcPtr[16 + column]; + + A3 = srcPtr[24 + column] + srcPtr[32 + column]; + A4 = srcPtr[24 + column] - srcPtr[32 + column]; + + A5 = srcPtr[40 + column] + srcPtr[48 + column]; + A6 = srcPtr[40 + column] - srcPtr[48 + column]; + + K0 = c4 * (A0 + A3); + K1 = c4 * (A1 + A5); + + dstPtr[ column] = .5f * (K0 + K1); + dstPtr[32+column] = .5f * (K0 - K1); + + // + // (2*dst2, 2*dst6) = rot 6 ( d12 - d56, s07 - s34 ) + // + + rot_x = A2 - A6; + rot_y = A0 - A3; + + dstPtr[16+column] = .5f * (c6 * rot_x + c2 * rot_y); + dstPtr[48+column] = .5f * (c6 * rot_y - c2 * rot_x); + + // + // K0, K1 are active until after dst[1],dst[7] + // as well as dst[3], dst[5] are computed. + // + + K0 = c4 * (A1 - A5); + K1 = -1 * c4 * (A2 + A6); + + // + // (2*dst3, 2*dst5) = rot -3 ( d07 - K0, d34 + K1 ) + // + + rot_x = A7 - K0; + rot_y = A4 + K1; + + dstPtr[24+column] = .5f * (c3 * rot_x - c5 * rot_y); + dstPtr[40+column] = .5f * (c5 * rot_x + c3 * rot_y); + + // + // (2*dst1, 2*dst7) = rot -1 ( d07 + K0, K1 - d34 ) + // + + rot_x = A7 + K0; + rot_y = K1 - A4; + + dstPtr[ 8+column] = .5f * (c1 * rot_x - c7 * rot_y); + dstPtr[56+column] = .5f * (c7 * rot_x + c1 * rot_y); + } +} + +#else /* IMF_HAVE_SSE2 */ + +// +// SSE2 implementation +// +// Here, we're always doing a column-wise operation +// plus transposes. This might be faster to do differently +// between rows-wise and column-wise +// + +void +dctForward8x8 (float *data) +{ + __m128 *srcVec = (__m128 *)data; + __m128 a0Vec, a1Vec, a2Vec, a3Vec, a4Vec, a5Vec, a6Vec, a7Vec; + __m128 k0Vec, k1Vec, rotXVec, rotYVec; + __m128 transTmp[4], transTmp2[4]; + + __m128 c4Vec = { .70710678f, .70710678f, .70710678f, .70710678f}; + __m128 c4NegVec = {-.70710678f, -.70710678f, -.70710678f, -.70710678f}; + + __m128 c1HalfVec = {.490392640f, .490392640f, .490392640f, .490392640f}; + __m128 c2HalfVec = {.461939770f, .461939770f, .461939770f, .461939770f}; + __m128 c3HalfVec = {.415734810f, .415734810f, .415734810f, .415734810f}; + __m128 c5HalfVec = {.277785120f, .277785120f, .277785120f, .277785120f}; + __m128 c6HalfVec = {.191341720f, .191341720f, .191341720f, .191341720f}; + __m128 c7HalfVec = {.097545161f, .097545161f, .097545161f, .097545161f}; + + __m128 halfVec = {.5f, .5f, .5f, .5f}; + + for (int iter = 0; iter < 2; ++iter) + { + // + // Operate on 4 columns at a time. The + // offsets into our row-major array are: + // 0: 0 1 + // 1: 2 3 + // 2: 4 5 + // 3: 6 7 + // 4: 8 9 + // 5: 10 11 + // 6: 12 13 + // 7: 14 15 + // + + for (int pass=0; pass<2; ++pass) + { + a0Vec = _mm_add_ps (srcVec[ 0 + pass], srcVec[14 + pass]); + a1Vec = _mm_add_ps (srcVec[ 2 + pass], srcVec[ 4 + pass]); + a3Vec = _mm_add_ps (srcVec[ 6 + pass], srcVec[ 8 + pass]); + a5Vec = _mm_add_ps (srcVec[10 + pass], srcVec[12 + pass]); + + a7Vec = _mm_sub_ps (srcVec[ 0 + pass], srcVec[14 + pass]); + a2Vec = _mm_sub_ps (srcVec[ 2 + pass], srcVec[ 4 + pass]); + a4Vec = _mm_sub_ps (srcVec[ 6 + pass], srcVec[ 8 + pass]); + a6Vec = _mm_sub_ps (srcVec[10 + pass], srcVec[12 + pass]); + + // + // First stage; Compute out_0 and out_4 + // + + k0Vec = _mm_add_ps (a0Vec, a3Vec); + k1Vec = _mm_add_ps (a1Vec, a5Vec); + + k0Vec = _mm_mul_ps (c4Vec, k0Vec); + k1Vec = _mm_mul_ps (c4Vec, k1Vec); + + srcVec[0 + pass] = _mm_add_ps (k0Vec, k1Vec); + srcVec[8 + pass] = _mm_sub_ps (k0Vec, k1Vec); + + srcVec[0 + pass] = _mm_mul_ps (srcVec[0 + pass], halfVec ); + srcVec[8 + pass] = _mm_mul_ps (srcVec[8 + pass], halfVec ); + + + // + // Second stage; Compute out_2 and out_6 + // + + k0Vec = _mm_sub_ps (a2Vec, a6Vec); + k1Vec = _mm_sub_ps (a0Vec, a3Vec); + + srcVec[ 4 + pass] = _mm_add_ps (_mm_mul_ps (c6HalfVec, k0Vec), + _mm_mul_ps (c2HalfVec, k1Vec)); + + srcVec[12 + pass] = _mm_sub_ps (_mm_mul_ps (c6HalfVec, k1Vec), + _mm_mul_ps (c2HalfVec, k0Vec)); + + // + // Precompute K0 and K1 for the remaining stages + // + + k0Vec = _mm_mul_ps (_mm_sub_ps (a1Vec, a5Vec), c4Vec); + k1Vec = _mm_mul_ps (_mm_add_ps (a2Vec, a6Vec), c4NegVec); + + // + // Third Stage, compute out_3 and out_5 + // + + rotXVec = _mm_sub_ps (a7Vec, k0Vec); + rotYVec = _mm_add_ps (a4Vec, k1Vec); + + srcVec[ 6 + pass] = _mm_sub_ps (_mm_mul_ps (c3HalfVec, rotXVec), + _mm_mul_ps (c5HalfVec, rotYVec)); + + srcVec[10 + pass] = _mm_add_ps (_mm_mul_ps (c5HalfVec, rotXVec), + _mm_mul_ps (c3HalfVec, rotYVec)); + + // + // Fourth Stage, compute out_1 and out_7 + // + + rotXVec = _mm_add_ps (a7Vec, k0Vec); + rotYVec = _mm_sub_ps (k1Vec, a4Vec); + + srcVec[ 2 + pass] = _mm_sub_ps (_mm_mul_ps (c1HalfVec, rotXVec), + _mm_mul_ps (c7HalfVec, rotYVec)); + + srcVec[14 + pass] = _mm_add_ps (_mm_mul_ps (c7HalfVec, rotXVec), + _mm_mul_ps (c1HalfVec, rotYVec)); + } + + // + // Transpose the matrix, in 4x4 blocks. So, if we have our + // 8x8 matrix divied into 4x4 blocks: + // + // M0 | M1 M0t | M2t + // ----+--- --> -----+------ + // M2 | M3 M1t | M3t + // + + // + // M0t, done in place, the first half. + // + + transTmp[0] = _mm_shuffle_ps (srcVec[0], srcVec[2], 0x44); + transTmp[1] = _mm_shuffle_ps (srcVec[4], srcVec[6], 0x44); + transTmp[3] = _mm_shuffle_ps (srcVec[4], srcVec[6], 0xEE); + transTmp[2] = _mm_shuffle_ps (srcVec[0], srcVec[2], 0xEE); + + // + // M3t, also done in place, the first half. + // + + transTmp2[0] = _mm_shuffle_ps (srcVec[ 9], srcVec[11], 0x44); + transTmp2[1] = _mm_shuffle_ps (srcVec[13], srcVec[15], 0x44); + transTmp2[2] = _mm_shuffle_ps (srcVec[ 9], srcVec[11], 0xEE); + transTmp2[3] = _mm_shuffle_ps (srcVec[13], srcVec[15], 0xEE); + + // + // M0t, the second half. + // + + srcVec[0] = _mm_shuffle_ps (transTmp[0], transTmp[1], 0x88); + srcVec[4] = _mm_shuffle_ps (transTmp[2], transTmp[3], 0x88); + srcVec[2] = _mm_shuffle_ps (transTmp[0], transTmp[1], 0xDD); + srcVec[6] = _mm_shuffle_ps (transTmp[2], transTmp[3], 0xDD); + + // + // M3t, the second half. + // + + srcVec[ 9] = _mm_shuffle_ps (transTmp2[0], transTmp2[1], 0x88); + srcVec[13] = _mm_shuffle_ps (transTmp2[2], transTmp2[3], 0x88); + srcVec[11] = _mm_shuffle_ps (transTmp2[0], transTmp2[1], 0xDD); + srcVec[15] = _mm_shuffle_ps (transTmp2[2], transTmp2[3], 0xDD); + + // + // M1 and M2 need to be done at the same time, because we're + // swapping. + // + // First, the first half of M1t + // + + transTmp[0] = _mm_shuffle_ps (srcVec[1], srcVec[3], 0x44); + transTmp[1] = _mm_shuffle_ps (srcVec[5], srcVec[7], 0x44); + transTmp[2] = _mm_shuffle_ps (srcVec[1], srcVec[3], 0xEE); + transTmp[3] = _mm_shuffle_ps (srcVec[5], srcVec[7], 0xEE); + + // + // And the first half of M2t + // + + transTmp2[0] = _mm_shuffle_ps (srcVec[ 8], srcVec[10], 0x44); + transTmp2[1] = _mm_shuffle_ps (srcVec[12], srcVec[14], 0x44); + transTmp2[2] = _mm_shuffle_ps (srcVec[ 8], srcVec[10], 0xEE); + transTmp2[3] = _mm_shuffle_ps (srcVec[12], srcVec[14], 0xEE); + + // + // Second half of M1t + // + + srcVec[ 8] = _mm_shuffle_ps (transTmp[0], transTmp[1], 0x88); + srcVec[12] = _mm_shuffle_ps (transTmp[2], transTmp[3], 0x88); + srcVec[10] = _mm_shuffle_ps (transTmp[0], transTmp[1], 0xDD); + srcVec[14] = _mm_shuffle_ps (transTmp[2], transTmp[3], 0xDD); + + // + // Second half of M2 + // + + srcVec[1] = _mm_shuffle_ps (transTmp2[0], transTmp2[1], 0x88); + srcVec[5] = _mm_shuffle_ps (transTmp2[2], transTmp2[3], 0x88); + srcVec[3] = _mm_shuffle_ps (transTmp2[0], transTmp2[1], 0xDD); + srcVec[7] = _mm_shuffle_ps (transTmp2[2], transTmp2[3], 0xDD); + } +} + +#endif /* IMF_HAVE_SSE2 */ + +} // anonymous namespace + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfEnvmap.cpp b/3rdparty/openexr/IlmImf/ImfEnvmap.cpp index f984aa3fca..f962fc96ee 100644 --- a/3rdparty/openexr/IlmImf/ImfEnvmap.cpp +++ b/3rdparty/openexr/IlmImf/ImfEnvmap.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,25 +39,30 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfEnvmap.h" #include "ImathFun.h" +#include "ImfNamespace.h" + #include #include using namespace std; -using namespace Imath; +using namespace IMATH_NAMESPACE; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + -namespace Imf { namespace LatLongMap { -V2f +V2f latLong (const V3f &dir) { float r = sqrt (dir.z * dir.z + dir.x * dir.x); float latitude = (r < abs (dir.y))? - acos (r / dir.length()) * sign (dir.y): - asin (dir.y / dir.length()); + acos (r / dir.length()) * sign (dir.y): + asin (dir.y / dir.length()); float longitude = (dir.z == 0 && dir.x == 0)? 0: atan2 (dir.x, dir.z); @@ -72,24 +77,24 @@ latLong (const Box2i &dataWindow, const V2f &pixelPosition) if (dataWindow.max.y > dataWindow.min.y) { - latitude = -M_PI * - ((pixelPosition.y - dataWindow.min.y) / - (dataWindow.max.y - dataWindow.min.y) - 0.5f); + latitude = -1 * float(M_PI) * + ((pixelPosition.y - dataWindow.min.y) / + (dataWindow.max.y - dataWindow.min.y) - 0.5f); } else { - latitude = 0; + latitude = 0; } if (dataWindow.max.x > dataWindow.min.x) { - longitude = -2 * M_PI * - ((pixelPosition.x - dataWindow.min.x) / - (dataWindow.max.x - dataWindow.min.x) - 0.5f); + longitude = -2 * float(M_PI) * + ((pixelPosition.x - dataWindow.min.x) / + (dataWindow.max.x - dataWindow.min.x) - 0.5f); } else { - longitude = 0; + longitude = 0; } return V2f (latitude, longitude); @@ -99,11 +104,11 @@ latLong (const Box2i &dataWindow, const V2f &pixelPosition) V2f pixelPosition (const Box2i &dataWindow, const V2f &latLong) { - float x = latLong.y / (-2 * M_PI) + 0.5f; - float y = latLong.x / -M_PI + 0.5f; + float x = latLong.y / (-2 * float(M_PI)) + 0.5f; + float y = latLong.x / (-1 * float(M_PI)) + 0.5f; return V2f (x * (dataWindow.max.x - dataWindow.min.x) + dataWindow.min.x, - y * (dataWindow.max.y - dataWindow.min.y) + dataWindow.min.y); + y * (dataWindow.max.y - dataWindow.min.y) + dataWindow.min.y); } @@ -120,8 +125,8 @@ direction (const Box2i &dataWindow, const V2f &pixelPosition) V2f ll = latLong (dataWindow, pixelPosition); return V3f (sin (ll.y) * cos (ll.x), - sin (ll.x), - cos (ll.y) * cos (ll.x)); + sin (ll.x), + cos (ll.y) * cos (ll.x)); } } // namespace LatLongMap @@ -133,7 +138,7 @@ int sizeOfFace (const Box2i &dataWindow) { return min ((dataWindow.max.x - dataWindow.min.x + 1), - (dataWindow.max.y - dataWindow.min.y + 1) / 6); + (dataWindow.max.y - dataWindow.min.y + 1) / 6); } @@ -163,39 +168,39 @@ pixelPosition (CubeMapFace face, const Box2i &dataWindow, V2f positionInFace) { case CUBEFACE_POS_X: - pos.x = dwf.min.x + positionInFace.y; - pos.y = dwf.max.y - positionInFace.x; - break; + pos.x = dwf.min.x + positionInFace.y; + pos.y = dwf.max.y - positionInFace.x; + break; case CUBEFACE_NEG_X: - pos.x = dwf.max.x - positionInFace.y; - pos.y = dwf.max.y - positionInFace.x; - break; + pos.x = dwf.max.x - positionInFace.y; + pos.y = dwf.max.y - positionInFace.x; + break; case CUBEFACE_POS_Y: - pos.x = dwf.min.x + positionInFace.x; - pos.y = dwf.max.y - positionInFace.y; - break; + pos.x = dwf.min.x + positionInFace.x; + pos.y = dwf.max.y - positionInFace.y; + break; case CUBEFACE_NEG_Y: - pos.x = dwf.min.x + positionInFace.x; - pos.y = dwf.min.y + positionInFace.y; - break; + pos.x = dwf.min.x + positionInFace.x; + pos.y = dwf.min.y + positionInFace.y; + break; case CUBEFACE_POS_Z: - pos.x = dwf.max.x - positionInFace.x; - pos.y = dwf.max.y - positionInFace.y; - break; + pos.x = dwf.max.x - positionInFace.x; + pos.y = dwf.max.y - positionInFace.y; + break; case CUBEFACE_NEG_Z: - pos.x = dwf.min.x + positionInFace.x; - pos.y = dwf.max.y - positionInFace.y; - break; + pos.x = dwf.min.x + positionInFace.x; + pos.y = dwf.max.y - positionInFace.y; + break; } return pos; @@ -204,9 +209,9 @@ pixelPosition (CubeMapFace face, const Box2i &dataWindow, V2f positionInFace) void faceAndPixelPosition (const V3f &direction, - const Box2i &dataWindow, - CubeMapFace &face, - V2f &pif) + const Box2i &dataWindow, + CubeMapFace &face, + V2f &pif) { int sof = sizeOfFace (dataWindow); float absx = abs (direction.x); @@ -215,44 +220,44 @@ faceAndPixelPosition (const V3f &direction, if (absx >= absy && absx >= absz) { - if (absx == 0) - { - // - // Special case - direction is (0, 0, 0) - // - - face = CUBEFACE_POS_X; - pif = V2f (0, 0); - return; - } - - pif.x = (direction.y / absx + 1) / 2 * (sof - 1); - pif.y = (direction.z / absx + 1) / 2 * (sof - 1); - - if (direction.x > 0) - face = CUBEFACE_POS_X; - else - face = CUBEFACE_NEG_X; + if (absx == 0) + { + // + // Special case - direction is (0, 0, 0) + // + + face = CUBEFACE_POS_X; + pif = V2f (0, 0); + return; + } + + pif.x = (direction.y / absx + 1) / 2 * (sof - 1); + pif.y = (direction.z / absx + 1) / 2 * (sof - 1); + + if (direction.x > 0) + face = CUBEFACE_POS_X; + else + face = CUBEFACE_NEG_X; } else if (absy >= absz) { - pif.x = (direction.x / absy + 1) / 2 * (sof - 1); - pif.y = (direction.z / absy + 1) / 2 * (sof - 1); + pif.x = (direction.x / absy + 1) / 2 * (sof - 1); + pif.y = (direction.z / absy + 1) / 2 * (sof - 1); - if (direction.y > 0) - face = CUBEFACE_POS_Y; - else - face = CUBEFACE_NEG_Y; + if (direction.y > 0) + face = CUBEFACE_POS_Y; + else + face = CUBEFACE_NEG_Y; } else { - pif.x = (direction.x / absz + 1) / 2 * (sof - 1); - pif.y = (direction.y / absz + 1) / 2 * (sof - 1); + pif.x = (direction.x / absz + 1) / 2 * (sof - 1); + pif.y = (direction.y / absz + 1) / 2 * (sof - 1); - if (direction.z > 0) - face = CUBEFACE_POS_Z; - else - face = CUBEFACE_NEG_Z; + if (direction.z > 0) + face = CUBEFACE_POS_Z; + else + face = CUBEFACE_NEG_Z; } } @@ -263,15 +268,15 @@ direction (CubeMapFace face, const Box2i &dataWindow, const V2f &positionInFace) int sof = sizeOfFace (dataWindow); V2f pos; - + if (sof > 1) { - pos = V2f (positionInFace.x / (sof - 1) * 2 - 1, - positionInFace.y / (sof - 1) * 2 - 1); + pos = V2f (positionInFace.x / (sof - 1) * 2 - 1, + positionInFace.y / (sof - 1) * 2 - 1); } else { - pos = V2f (0, 0); + pos = V2f (0, 0); } V3f dir (1, 0, 0); @@ -280,49 +285,51 @@ direction (CubeMapFace face, const Box2i &dataWindow, const V2f &positionInFace) { case CUBEFACE_POS_X: - dir.x = 1; - dir.y = pos.x; - dir.z = pos.y; - break; + dir.x = 1; + dir.y = pos.x; + dir.z = pos.y; + break; case CUBEFACE_NEG_X: - dir.x = -1; - dir.y = pos.x; - dir.z = pos.y; - break; + dir.x = -1; + dir.y = pos.x; + dir.z = pos.y; + break; case CUBEFACE_POS_Y: - dir.x = pos.x; - dir.y = 1; - dir.z = pos.y; - break; + dir.x = pos.x; + dir.y = 1; + dir.z = pos.y; + break; case CUBEFACE_NEG_Y: - dir.x = pos.x; - dir.y = -1; - dir.z = pos.y; - break; + dir.x = pos.x; + dir.y = -1; + dir.z = pos.y; + break; case CUBEFACE_POS_Z: - dir.x = pos.x; - dir.y = pos.y; - dir.z = 1; - break; + dir.x = pos.x; + dir.y = pos.y; + dir.z = 1; + break; case CUBEFACE_NEG_Z: - dir.x = pos.x; - dir.y = pos.y; - dir.z = -1; - break; + dir.x = pos.x; + dir.y = pos.y; + dir.z = -1; + break; } return dir; } } // namespace CubeMap -} // namespace Imf + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfEnvmap.h b/3rdparty/openexr/IlmImf/ImfEnvmap.h index b82ca52774..16e4ee3ee5 100644 --- a/3rdparty/openexr/IlmImf/ImfEnvmap.h +++ b/3rdparty/openexr/IlmImf/ImfEnvmap.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -73,8 +73,11 @@ //----------------------------------------------------------------------------- #include "ImathBox.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER //-------------------------------- // Supported environment map types @@ -116,7 +119,8 @@ namespace LatLongMap // and longitude. //---------------------------------------------------- - Imath::V2f latLong (const Imath::V3f &direction); + IMF_EXPORT + IMATH_NAMESPACE::V2f latLong (const IMATH_NAMESPACE::V3f &direction); //-------------------------------------------------------- @@ -125,8 +129,9 @@ namespace LatLongMap // and longitude. //-------------------------------------------------------- - Imath::V2f latLong (const Imath::Box2i &dataWindow, - const Imath::V2f &pixelPosition); + IMF_EXPORT + IMATH_NAMESPACE::V2f latLong (const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V2f &pixelPosition); //------------------------------------------------------------- @@ -134,8 +139,9 @@ namespace LatLongMap // longitude and latitude, into a corresponding pixel position. //------------------------------------------------------------- - Imath::V2f pixelPosition (const Imath::Box2i &dataWindow, - const Imath::V2f &latLong); + IMF_EXPORT + IMATH_NAMESPACE::V2f pixelPosition (const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V2f &latLong); //----------------------------------------------------- @@ -144,8 +150,9 @@ namespace LatLongMap // to pixelPosition(dw,latLong(dw,dir)). //----------------------------------------------------- - Imath::V2f pixelPosition (const Imath::Box2i &dataWindow, - const Imath::V3f &direction); + IMF_EXPORT + IMATH_NAMESPACE::V2f pixelPosition (const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V3f &direction); //-------------------------------------------------------- @@ -153,8 +160,9 @@ namespace LatLongMap // map into a corresponding 3D direction. //-------------------------------------------------------- - Imath::V3f direction (const Imath::Box2i &dataWindow, - const Imath::V2f &pixelPosition); + IMF_EXPORT + IMATH_NAMESPACE::V3f direction (const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V2f &pixelPosition); } @@ -177,10 +185,10 @@ namespace LatLongMap // | | / / // | |/ / // 4-----------5 Z -// +// // dataWindow.min // / -// / +// / // +-----------+ // |3 Y 7| // | | | @@ -237,7 +245,7 @@ namespace LatLongMap // The size of the data window should be N by 6*N pixels // (width by height), where N can be any integer greater // than 0. -// +// //-------------------------------------------------------------- //------------------------------------ @@ -260,7 +268,8 @@ namespace CubeMap // Width and height of a cube's face, in pixels //--------------------------------------------- - int sizeOfFace (const Imath::Box2i &dataWindow); + IMF_EXPORT + int sizeOfFace (const IMATH_NAMESPACE::Box2i &dataWindow); //------------------------------------------ @@ -268,8 +277,9 @@ namespace CubeMap // that is covered by the specified face. //------------------------------------------ - Imath::Box2i dataWindowForFace (CubeMapFace face, - const Imath::Box2i &dataWindow); + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForFace (CubeMapFace face, + const IMATH_NAMESPACE::Box2i &dataWindow); //---------------------------------------------------- @@ -279,9 +289,10 @@ namespace CubeMap // in the environment map. //---------------------------------------------------- - Imath::V2f pixelPosition (CubeMapFace face, - const Imath::Box2i &dataWindow, - Imath::V2f positionInFace); + IMF_EXPORT + IMATH_NAMESPACE::V2f pixelPosition (CubeMapFace face, + const IMATH_NAMESPACE::Box2i &dataWindow, + IMATH_NAMESPACE::V2f positionInFace); //-------------------------------------------------------------- @@ -300,23 +311,26 @@ namespace CubeMap // //-------------------------------------------------------------- - void faceAndPixelPosition (const Imath::V3f &direction, - const Imath::Box2i &dataWindow, - CubeMapFace &face, - Imath::V2f &positionInFace); - + IMF_EXPORT + void faceAndPixelPosition (const IMATH_NAMESPACE::V3f &direction, + const IMATH_NAMESPACE::Box2i &dataWindow, + CubeMapFace &face, + IMATH_NAMESPACE::V2f &positionInFace); + // -------------------------------------------------------- // Given a cube face and a pixel position within that face, // compute the corresponding 3D direction. // -------------------------------------------------------- - Imath::V3f direction (CubeMapFace face, - const Imath::Box2i &dataWindow, - const Imath::V2f &positionInFace); + IMF_EXPORT + IMATH_NAMESPACE::V3f direction (CubeMapFace face, + const IMATH_NAMESPACE::Box2i &dataWindow, + const IMATH_NAMESPACE::V2f &positionInFace); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + #endif diff --git a/3rdparty/openexr/IlmImf/ImfEnvmapAttribute.cpp b/3rdparty/openexr/IlmImf/ImfEnvmapAttribute.cpp index a0eefc5765..b6f88c27d1 100644 --- a/3rdparty/openexr/IlmImf/ImfEnvmapAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfEnvmapAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,8 +42,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -55,7 +56,7 @@ EnvmapAttribute::staticTypeName () template <> void -EnvmapAttribute::writeValueTo (OStream &os, int) const +EnvmapAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { unsigned char tmp = _value; Xdr::write (os, tmp); @@ -64,7 +65,7 @@ EnvmapAttribute::writeValueTo (OStream &os, int) const template <> void -EnvmapAttribute::readValueFrom (IStream &is, int, int) +EnvmapAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { unsigned char tmp; Xdr::read (is, tmp); @@ -72,4 +73,4 @@ EnvmapAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfEnvmapAttribute.h b/3rdparty/openexr/IlmImf/ImfEnvmapAttribute.h index 6ac73aadac..0d0129b80a 100644 --- a/3rdparty/openexr/IlmImf/ImfEnvmapAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfEnvmapAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,24 +42,27 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfEnvmap.h" +#include "ImfExport.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { +typedef TypedAttribute EnvmapAttribute; -typedef TypedAttribute EnvmapAttribute; -template <> const char *EnvmapAttribute::staticTypeName (); -template <> void EnvmapAttribute::writeValueTo (OStream &, int) const; -template <> void EnvmapAttribute::readValueFrom (IStream &, int, int); +template <> IMF_EXPORT const char *EnvmapAttribute::staticTypeName (); +template <> IMF_EXPORT +void EnvmapAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; -} // namespace Imf +template <> IMF_EXPORT +void EnvmapAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, + int); -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfExport.h b/3rdparty/openexr/IlmImf/ImfExport.h new file mode 100644 index 0000000000..6563fd5e3e --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfExport.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#if defined(OPENEXR_DLL) + #if defined(ILMIMF_EXPORTS) + #define IMF_EXPORT __declspec(dllexport) + #define IMF_EXPORT_CONST extern __declspec(dllexport) + #else + #define IMF_EXPORT __declspec(dllimport) + #define IMF_EXPORT_CONST extern __declspec(dllimport) + #endif +#else + #define IMF_EXPORT + #define IMF_EXPORT_CONST extern const +#endif diff --git a/3rdparty/openexr/IlmImf/ImfFastHuf.cpp b/3rdparty/openexr/IlmImf/ImfFastHuf.cpp new file mode 100644 index 0000000000..e581c0f25a --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfFastHuf.cpp @@ -0,0 +1,768 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2009-2014 DreamWorks Animation LLC. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of DreamWorks Animation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfFastHuf.h" +#include + +#include +#include +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +// +// Adapted from hufUnpackEncTable - +// We don't need to reconstruct the code book, just the encoded +// lengths for each symbol. From the lengths, we can build the +// base + offset tables. This should be a bit more efficient +// for sparse code books. +// +// table - ptr to the start of the code length data. Will be +// updated as we decode data +// +// numBytes - size of the encoded table (I think)? +// +// minSymbol - smallest symbol in the code book +// +// maxSymbol - largest symbol in the code book. +// +// rleSymbol - the symbol to trigger RLE in the encoded bitstream +// + +FastHufDecoder::FastHufDecoder + (const char *&table, + int numBytes, + int minSymbol, + int maxSymbol, + int rleSymbol) +: + _rleSymbol (rleSymbol), + _numSymbols (0), + _minCodeLength (255), + _maxCodeLength (0), + _idToSymbol (0) +{ + // + // List of symbols that we find with non-zero code lengths + // (listed in the order we find them). Store these in the + // same format as the code book stores codes + lengths - + // low 6 bits are the length, everything above that is + // the symbol. + // + + std::vector symbols; + + // + // The 'base' table is the minimum code at each code length. base[i] + // is the smallest code (numerically) of length i. + // + + Int64 base[MAX_CODE_LEN + 1]; + + // + // The 'offset' table is the position (in sorted order) of the first id + // of a given code lenght. Array is indexed by code length, like base. + // + + Int64 offset[MAX_CODE_LEN + 1]; + + // + // Count of how many codes at each length there are. Array is + // indexed by code length, like base and offset. + // + + size_t codeCount[MAX_CODE_LEN + 1]; + + for (int i = 0; i <= MAX_CODE_LEN; ++i) + { + codeCount[i] = 0; + base[i] = 0xffffffffffffffffULL; + offset[i] = 0; + } + + // + // Count the number of codes, the min/max code lengths, the number of + // codes with each length, and record symbols with non-zero code + // length as we find them. + // + + const char *currByte = table; + Int64 currBits = 0; + int currBitCount = 0; + + const int SHORT_ZEROCODE_RUN = 59; + const int LONG_ZEROCODE_RUN = 63; + const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN; + + for (Int64 symbol = minSymbol; symbol <= maxSymbol; symbol++) + { + if (currByte - table > numBytes) + { + throw IEX_NAMESPACE::InputExc ("Error decoding Huffman table " + "(Truncated table data)."); + } + + // + // Next code length - either: + // 0-58 (literal code length) + // 59-62 (various lengths runs of 0) + // 63 (run of n 0's, with n is the next 8 bits) + // + + Int64 codeLen = readBits (6, currBits, currBitCount, currByte); + + if (codeLen == (Int64) LONG_ZEROCODE_RUN) + { + if (currByte - table > numBytes) + { + throw IEX_NAMESPACE::InputExc ("Error decoding Huffman table " + "(Truncated table data)."); + } + + int runLen = readBits (8, currBits, currBitCount, currByte) + + SHORTEST_LONG_RUN; + + if (symbol + runLen > maxSymbol + 1) + { + throw IEX_NAMESPACE::InputExc ("Error decoding Huffman table " + "(Run beyond end of table)."); + } + + symbol += runLen - 1; + + } + else if (codeLen >= (Int64) SHORT_ZEROCODE_RUN) + { + int runLen = codeLen - SHORT_ZEROCODE_RUN + 2; + + if (symbol + runLen > maxSymbol + 1) + { + throw IEX_NAMESPACE::InputExc ("Error decoding Huffman table " + "(Run beyond end of table)."); + } + + symbol += runLen - 1; + + } + else if (codeLen != 0) + { + symbols.push_back ((symbol << 6) | (codeLen & 63)); + + if (codeLen < _minCodeLength) + _minCodeLength = codeLen; + + if (codeLen > _maxCodeLength) + _maxCodeLength = codeLen; + + codeCount[codeLen]++; + } + } + + for (int i = 0; i < MAX_CODE_LEN; ++i) + _numSymbols += codeCount[i]; + + table = currByte; + + // + // Compute base - once we have the code length counts, there + // is a closed form solution for this + // + + { + double* countTmp = new double[_maxCodeLength+1]; + + for (int l = _minCodeLength; l <= _maxCodeLength; ++l) + { + countTmp[l] = (double)codeCount[l] * + (double)(2 << (_maxCodeLength-l)); + } + + for (int l = _minCodeLength; l <= _maxCodeLength; ++l) + { + double tmp = 0; + + for (int k =l + 1; k <= _maxCodeLength; ++k) + tmp += countTmp[k]; + + tmp /= (double)(2 << (_maxCodeLength - l)); + + base[l] = (Int64)ceil (tmp); + } + + delete [] countTmp; + } + + // + // Compute offset - these are the positions of the first + // id (not symbol) that has length [i] + // + + offset[_maxCodeLength] = 0; + + for (int i= _maxCodeLength - 1; i >= _minCodeLength; i--) + offset[i] = offset[i + 1] + codeCount[i + 1]; + + // + // Allocate and fill the symbol-to-id mapping. Smaller Ids should be + // mapped to less-frequent symbols (which have longer codes). Use + // the offset table to tell us where the id's for a given code + // length start off. + // + + _idToSymbol = new int[_numSymbols]; + + Int64 mapping[MAX_CODE_LEN + 1]; + for (int i = 0; i < MAX_CODE_LEN + 1; ++i) + mapping[i] = -1; + for (int i = _minCodeLength; i <= _maxCodeLength; ++i) + mapping[i] = offset[i]; + + for (std::vector::const_iterator i = symbols.begin(); + i != symbols.end(); + ++i) + { + int codeLen = *i & 63; + int symbol = *i >> 6; + + if (mapping[codeLen] >= _numSymbols) + throw IEX_NAMESPACE::InputExc ("Huffman decode error " + "(Invalid symbol in header)."); + + _idToSymbol[mapping[codeLen]] = symbol; + mapping[codeLen]++; + } + + buildTables(base, offset); +} + + +FastHufDecoder::~FastHufDecoder() +{ + delete[] _idToSymbol; +} + + +// +// Static check if the decoder is enabled. +// +// ATM, I only have access to little endian hardware for testing, +// so I'm not entirely sure that we are reading fom the bit stream +// properly on BE. +// +// If you happen to have more obscure hardware, check that the +// byte swapping in refill() is happening sensable, add an endian +// check if needed, and fix the preprocessor magic here. +// + +#define READ64(c) \ + ((Int64)(c)[0] << 56) | ((Int64)(c)[1] << 48) | ((Int64)(c)[2] << 40) | \ + ((Int64)(c)[3] << 32) | ((Int64)(c)[4] << 24) | ((Int64)(c)[5] << 16) | \ + ((Int64)(c)[6] << 8) | ((Int64)(c)[7] ) + +#ifdef __INTEL_COMPILER // ICC built-in swap for LE hosts + #if defined (__i386__) || defined(__x86_64__) + #undef READ64 + #define READ64(c) _bswap64 (*(const Int64*)(c)) + #endif +#endif + + +bool +FastHufDecoder::enabled() +{ + #if defined(__INTEL_COMPILER) || defined(__GNUC__) + + // + // Enabled for ICC, GCC: + // __i386__ -> x86 + // __x86_64__ -> 64-bit x86 + // + + #if defined (__i386__) || defined(__x86_64__) + return true; + #else + return false; + #endif + + #elif defined (_MSC_VER) + + // + // Enabled for Visual Studio: + // _M_IX86 -> x86 + // _M_X64 -> 64bit x86 + + #if defined (_M_IX86) || defined(_M_X64) + return true; + #else + return false; + #endif + + #else + + // + // Unknown compiler - Be safe and disable. + // + return false; + #endif +} + +// +// +// Built the acceleration tables for lookups on the upper bits +// as well as the 'LJ' tables. +// + +void +FastHufDecoder::buildTables (Int64 *base, Int64 *offset) +{ + // + // Build the 'left justified' base table, by shifting base left.. + // + + for (int i = 0; i <= MAX_CODE_LEN; ++i) + { + if (base[i] != 0xffffffffffffffffULL) + { + _ljBase[i] = base[i] << (64 - i); + } + else + { + // + // Unused code length - insert dummy values + // + + _ljBase[i] = 0xffffffffffffffffULL; + } + } + + // + // Combine some terms into a big fat constant, which for + // lack of a better term we'll call the 'left justified' + // offset table (because it serves the same function + // as 'offset', when using the left justified base table. + // + + for (int i = 0; i <= MAX_CODE_LEN; ++i) + _ljOffset[i] = offset[i] - (_ljBase[i] >> (64 - i)); + + // + // Build the acceleration tables for the lookups of + // short codes ( <= TABLE_LOOKUP_BITS long) + // + + for (Int64 i = 0; i < 1 << TABLE_LOOKUP_BITS; ++i) + { + Int64 value = i << (64 - TABLE_LOOKUP_BITS); + + _tableSymbol[i] = 0xffff; + _tableCodeLen[i] = 0; + + for (int codeLen = _minCodeLength; codeLen <= _maxCodeLength; ++codeLen) + { + if (_ljBase[codeLen] <= value) + { + _tableCodeLen[i] = codeLen; + + Int64 id = _ljOffset[codeLen] + (value >> (64 - codeLen)); + if (id < _numSymbols) + { + _tableSymbol[i] = _idToSymbol[id]; + } + else + { + throw IEX_NAMESPACE::InputExc ("Huffman decode error " + "(Overrun)."); + } + break; + } + } + } + + // + // Store the smallest value in the table that points to real data. + // This should be the entry for the largest length that has + // valid data (in our case, non-dummy _ljBase) + // + + int minIdx = TABLE_LOOKUP_BITS; + + while (minIdx > 0 && _ljBase[minIdx] == 0xffffffffffffffffULL) + minIdx--; + + if (minIdx < 0) + { + // + // Error, no codes with lengths 0-TABLE_LOOKUP_BITS used. + // Set the min value such that the table is never tested. + // + + _tableMin = 0xffffffffffffffffULL; + } + else + { + _tableMin = _ljBase[minIdx]; + } +} + + +// +// For decoding, we're holding onto 2 Int64's. +// +// The first (buffer), holds the next bits from the bitstream to be +// decoded. For certain paths in the decoder, we only need TABLE_LOOKUP_BITS +// valid bits to decode the next symbol. For other paths, we need a full +// 64-bits to decode a symbol. +// +// When we need to refill 'buffer', we could pull bits straight from +// the bitstream. But this is very slow and requires lots of book keeping +// (what's the next bit in the next byte?). Instead, we keep another Int64 +// around that we use to refill from. While this doesn't cut down on the +// book keeping (still need to know how many valid bits), it does cut +// down on some of the bit shifting crazy and byte access. +// +// The refill Int64 (bufferBack) gets left-shifted after we've pulled +// off bits. If we run out of bits in the input bit stream, we just +// shift in 0's to bufferBack. +// +// The refill act takes numBits from the top of bufferBack and sticks +// them in the bottom of buffer. If there arn't enough bits in bufferBack, +// it gets refilled (to 64-bits) from the input bitstream. +// + +inline void +FastHufDecoder::refill + (Int64 &buffer, + int numBits, // number of bits to refill + Int64 &bufferBack, // the next 64-bits, to refill from + int &bufferBackNumBits, // number of bits left in bufferBack + const unsigned char *&currByte, // current byte in the bitstream + int &currBitsLeft) // number of bits left in the bitsream +{ + // + // Refill bits into the bottom of buffer, from the top of bufferBack. + // Always top up buffer to be completely full. + // + + buffer |= bufferBack >> (64 - numBits); + + if (bufferBackNumBits < numBits) + { + numBits -= bufferBackNumBits; + + // + // Refill all of bufferBack from the bitstream. Either grab + // a full 64-bit chunk, or whatever bytes are left. If we + // don't have 64-bits left, pad with 0's. + // + + if (currBitsLeft >= 64) + { + bufferBack = READ64 (currByte); + bufferBackNumBits = 64; + currByte += sizeof (Int64); + currBitsLeft -= 8 * sizeof (Int64); + + } + else + { + bufferBack = 0; + bufferBackNumBits = 64; + + Int64 shift = 56; + + while (currBitsLeft > 0) + { + bufferBack |= ((Int64)(*currByte)) << shift; + + currByte++; + shift -= 8; + currBitsLeft -= 8; + } + + // + // At this point, currBitsLeft might be negative, just because + // we're subtracting whole bytes. To keep anyone from freaking + // out, zero the counter. + // + + if (currBitsLeft < 0) + currBitsLeft = 0; + } + + buffer |= bufferBack >> (64 - numBits); + } + + bufferBack = bufferBack << numBits; + bufferBackNumBits -= numBits; + + // + // We can have cases where the previous shift of bufferBack is << 64 - + // in which case no shift occurs. The bit count math still works though, + // so if we don't have any bits left, zero out bufferBack. + // + + if (bufferBackNumBits == 0) + bufferBack = 0; +} + +// +// Read the next few bits out of a bitstream. Will be given a backing buffer +// (buffer) that may still have data left over from previous reads +// (bufferNumBits). Bitstream pointer (currByte) will be advanced when needed. +// + +inline Int64 +FastHufDecoder::readBits + (int numBits, + Int64 &buffer, // c + int &bufferNumBits, // lc + const char *&currByte) // in +{ + while (bufferNumBits < numBits) + { + buffer = (buffer << 8) | *(unsigned char*)(currByte++); + bufferNumBits += 8; + } + + bufferNumBits -= numBits; + return (buffer >> bufferNumBits) & ((1 << numBits) - 1); +} + + +// +// Decode using a the 'One-Shift' strategy for decoding, with a +// small-ish table to accelerate decoding of short codes. +// +// If possible, try looking up codes into the acceleration table. +// This has a few benifits - there's no search involved; We don't +// need an additional lookup to map id to symbol; we don't need +// a full 64-bits (so less refilling). +// + +void +FastHufDecoder::decode + (const unsigned char *src, + int numSrcBits, + unsigned short *dst, + int numDstElems) +{ + if (numSrcBits < 128) + throw IEX_NAMESPACE::InputExc ("Error choosing Huffman decoder implementation " + "(insufficient number of bits)."); + + // + // Current position (byte/bit) in the src data stream + // (after the first buffer fill) + // + + const unsigned char *currByte = src + 2 * sizeof (Int64); + + numSrcBits -= 8 * 2 * sizeof (Int64); + + // + // 64-bit buffer holding the current bits in the stream + // + + Int64 buffer = READ64 (src); + int bufferNumBits = 64; + + // + // 64-bit buffer holding the next bits in the stream + // + + Int64 bufferBack = READ64 ((src + sizeof (Int64))); + int bufferBackNumBits = 64; + + int dstIdx = 0; + + while (dstIdx < numDstElems) + { + int codeLen; + int symbol; + + // + // Test if we can be table accelerated. If so, directly + // lookup the output symbol. Otherwise, we need to fall + // back to searching for the code. + // + // If we're doing table lookups, we don't really need + // a re-filled buffer, so long as we have TABLE_LOOKUP_BITS + // left. But for a search, we do need a refilled table. + // + + if (_tableMin <= buffer) + { + int tableIdx = buffer >> (64 - TABLE_LOOKUP_BITS); + + // + // For invalid codes, _tableCodeLen[] should return 0. This + // will cause the decoder to get stuck in the current spot + // until we run out of elements, then barf that the codestream + // is bad. So we don't need to stick a condition like + // if (codeLen > _maxCodeLength) in this inner. + // + + codeLen = _tableCodeLen[tableIdx]; + symbol = _tableSymbol[tableIdx]; + } + else + { + if (bufferNumBits < 64) + { + refill (buffer, + 64 - bufferNumBits, + bufferBack, + bufferBackNumBits, + currByte, + numSrcBits); + + bufferNumBits = 64; + } + + // + // Brute force search: + // Find the smallest length where _ljBase[length] <= buffer + // + + codeLen = TABLE_LOOKUP_BITS + 1; + + while (_ljBase[codeLen] > buffer && codeLen <= _maxCodeLength) + codeLen++; + + if (codeLen > _maxCodeLength) + { + throw IEX_NAMESPACE::InputExc ("Huffman decode error " + "(Decoded an invalid symbol)."); + } + + Int64 id = _ljOffset[codeLen] + (buffer >> (64 - codeLen)); + if (id < _numSymbols) + { + symbol = _idToSymbol[id]; + } + else + { + throw IEX_NAMESPACE::InputExc ("Huffman decode error " + "(Decoded an invalid symbol)."); + } + } + + // + // Shift over bit stream, and update the bit count in the buffer + // + + buffer = buffer << codeLen; + bufferNumBits -= codeLen; + + // + // If we recieved a RLE symbol (_rleSymbol), then we need + // to read ahead 8 bits to know how many times to repeat + // the previous symbol. Need to ensure we at least have + // 8 bits of data in the buffer + // + + if (symbol == _rleSymbol) + { + if (bufferNumBits < 8) + { + refill (buffer, + 64 - bufferNumBits, + bufferBack, + bufferBackNumBits, + currByte, + numSrcBits); + + bufferNumBits = 64; + } + + int rleCount = buffer >> 56; + + if (dstIdx < 1) + { + throw IEX_NAMESPACE::InputExc ("Huffman decode error (RLE code " + "with no previous symbol)."); + } + + if (dstIdx + rleCount > numDstElems) + { + throw IEX_NAMESPACE::InputExc ("Huffman decode error (Symbol run " + "beyond expected output buffer length)."); + } + + if (rleCount <= 0) + { + throw IEX_NAMESPACE::InputExc("Huffman decode error" + " (Invalid RLE length)"); + } + + for (int i = 0; i < rleCount; ++i) + dst[dstIdx + i] = dst[dstIdx - 1]; + + dstIdx += rleCount; + + buffer = buffer << 8; + bufferNumBits -= 8; + } + else + { + dst[dstIdx] = symbol; + dstIdx++; + } + + // + // refill bit stream buffer if we're below the number of + // bits needed for a table lookup + // + + if (bufferNumBits < TABLE_LOOKUP_BITS) + { + refill (buffer, + 64 - bufferNumBits, + bufferBack, + bufferBackNumBits, + currByte, + numSrcBits); + + bufferNumBits = 64; + } + } + + if (numSrcBits != 0) + { + throw IEX_NAMESPACE::InputExc ("Huffman decode error (Compressed data remains " + "after filling expected output buffer)."); + } +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfFastHuf.h b/3rdparty/openexr/IlmImf/ImfFastHuf.h new file mode 100644 index 0000000000..c8c84fdf51 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfFastHuf.h @@ -0,0 +1,153 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2009-2014 DreamWorks Animation LLC. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of DreamWorks Animation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMF_FAST_HUF_H +#define INCLUDED_IMF_FAST_HUF_H + +#include "ImfInt64.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Alternative Canonical Huffman decoder: +// +// Canonical Huffman decoder based on 'On the Implementation of Minimum +// Redundancy Prefix Codes' by Moffat and Turpin - highly recommended +// reading as a good description of the problem space, as well as +// a fast decoding algorithm. +// +// The premise is that instead of working directly with the coded +// symbols, we create a new ordering based on the frequency of symbols. +// Less frequent symbols (and thus longer codes) are ordered earler. +// We're calling the values in this ordering 'Ids', as oppsed to +// 'Symbols' - which are the short values we eventually want decoded. +// +// With this new ordering, a few small tables can be derived ('base' +// and 'offset') which drive the decoding. To cut down on the +// linear scanning of these tables, you can add a small table +// to directly look up short codes (as you might in a traditional +// lookup-table driven decoder). +// +// The decoder is meant to be compatible with the encoder (and decoder) +// in ImfHuf.cpp, just faster. For ease of implementation, this decoder +// should only be used on compressed bitstreams >= 128 bits long. +// + +class FastHufDecoder +{ + public: + + // + // Longest compressed code length that ImfHuf supports (58 bits) + // + + static const int MAX_CODE_LEN = 58; + + // + // Number of bits in our acceleration table. Should match all + // codes up to TABLE_LOOKUP_BITS in length. + // + + static const int TABLE_LOOKUP_BITS = 12; + + IMF_EXPORT + FastHufDecoder (const char*& table, + int numBytes, + int minSymbol, + int maxSymbol, + int rleSymbol); + + IMF_EXPORT + ~FastHufDecoder (); + + IMF_EXPORT + static bool enabled (); + + IMF_EXPORT + void decode (const unsigned char *src, + int numSrcBits, + unsigned short *dst, + int numDstElems); + + private: + + void buildTables (Int64*, Int64*); + void refill (Int64&, int, Int64&, int&, const unsigned char *&, int&); + Int64 readBits (int, Int64&, int&, const char *&); + + int _rleSymbol; // RLE symbol written by the encoder. + // This could be 65536, so beware + // when you use shorts to hold things. + + int _numSymbols; // Number of symbols in the codebook. + + unsigned char _minCodeLength; // Minimum code length, in bits. + unsigned char _maxCodeLength; // Maximum code length, in bits. + + int *_idToSymbol; // Maps Ids to symbols. Ids are a symbol + // ordering sorted first in terms of + // code length, and by code within + // the same length. Ids run from 0 + // to mNumSymbols-1. + + Int64 _ljBase[MAX_CODE_LEN + 1]; // the 'left justified base' table. + // Takes base[i] (i = code length) + // and 'left justifies' it into an Int64 + + Int64 _ljOffset[MAX_CODE_LEN +1 ]; // There are some other terms that can + // be folded into constants when taking + // the 'left justified' decode path. This + // holds those constants, indexed by + // code length + + // + // We can accelerate the 'left justified' processing by running the + // top TABLE_LOOKUP_BITS through a LUT, to find the symbol and code + // length. These are those acceleration tables. + // + // Even though our evental 'symbols' are ushort's, the encoder adds + // a symbol to indicate RLE. So with a dense code book, we could + // have 2^16+1 codes, so both mIdToSymbol and mTableSymbol need + // to be bigger than 16 bits. + // + + int _tableSymbol[1 << TABLE_LOOKUP_BITS]; + unsigned char _tableCodeLen[1 << TABLE_LOOKUP_BITS]; + Int64 _tableMin; +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfFloatAttribute.cpp b/3rdparty/openexr/IlmImf/ImfFloatAttribute.cpp index 3896cca374..4e22e90779 100644 --- a/3rdparty/openexr/IlmImf/ImfFloatAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfFloatAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,7 +43,7 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER template <> @@ -54,4 +54,4 @@ FloatAttribute::staticTypeName () } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfFloatAttribute.h b/3rdparty/openexr/IlmImf/ImfFloatAttribute.h index 95eaff6eb0..737072146e 100644 --- a/3rdparty/openexr/IlmImf/ImfFloatAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfFloatAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,21 +43,16 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfAttribute.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER typedef TypedAttribute FloatAttribute; -template <> const char *FloatAttribute::staticTypeName (); +template <> IMF_EXPORT const char *FloatAttribute::staticTypeName (); -} // namespace Imf - -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/b44ExpLogTable.cpp b/3rdparty/openexr/IlmImf/ImfFloatVectorAttribute.cpp similarity index 51% rename from 3rdparty/openexr/IlmImf/b44ExpLogTable.cpp rename to 3rdparty/openexr/IlmImf/ImfFloatVectorAttribute.cpp index 990738a578..49eda908fd 100644 --- a/3rdparty/openexr/IlmImf/b44ExpLogTable.cpp +++ b/3rdparty/openexr/IlmImf/ImfFloatVectorAttribute.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2013, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,105 +32,53 @@ // /////////////////////////////////////////////////////////////////////////// -//--------------------------------------------------------------------------- -// -// b44ExpLogTable -// -// A program to generate lookup tables for -// -// y = exp (x / 8) -// -// and -// x = 8 * log (x); -// -// where x and y are 16-bit floating-point numbers + +//----------------------------------------------------------------------------- // -// The tables are used by class B44Compressor. +// class FloatVectorAttribute // -//--------------------------------------------------------------------------- +//----------------------------------------------------------------------------- -#include -#include -#include -#include +#include -using namespace std; - -//--------------------------------------------- -// Main - prints the half-to-float lookup table -//--------------------------------------------- - -int -main () -{ -#ifndef HAVE_IOS_BASE - cout.setf (ios::hex, ios::basefield); -#else - cout.setf (ios_base::hex, ios_base::basefield); -#endif - cout << "//\n" - "// This is an automatically generated file.\n" - "// Do not edit.\n" - "//\n\n"; +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER - const int iMax = (1 << 16); - cout << "const unsigned short expTable[] =\n" - "{\n" - " "; +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; - for (int i = 0; i < iMax; i++) - { - half h; - h.setBits (i); - if (!h.isFinite()) - h = 0; - else if (h >= 8 * log (HALF_MAX)) - h = HALF_MAX; - else - h = exp (h / 8); - - cout << "0x" << setfill ('0') << setw (4) << h.bits() << ", "; - - if (i % 8 == 7) - { - cout << "\n"; - - if (i < iMax - 1) - cout << " "; - } - } - - cout << "};\n\n"; +template <> +const char * +FloatVectorAttribute::staticTypeName () +{ + return "floatvector"; +} - cout << "const unsigned short logTable[] =\n" - "{\n" - " "; - for (int i = 0; i < iMax; i++) - { - half h; - h.setBits (i); +template <> +void +FloatVectorAttribute::writeValueTo + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const +{ + int n = _value.size(); - if (!h.isFinite() || h < 0) - h = 0; - else - h = 8 * log (h); + for (int i = 0; i < n; ++i) + Xdr::write (os, _value[i]); +} - cout << "0x" << setfill ('0') << setw (4) << h.bits() << ", "; - if (i % 8 == 7) - { - cout << "\n"; +template <> +void +FloatVectorAttribute::readValueFrom + (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) +{ + int n = size / Xdr::size(); + _value.resize (n); - if (i < iMax - 1) - cout << " "; - } - } + for (int i = 0; i < n; ++i) + Xdr::read (is, _value[i]); +} - cout << "};\n"; - return 0; -} +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfFloatVectorAttribute.h b/3rdparty/openexr/IlmImf/ImfFloatVectorAttribute.h new file mode 100644 index 0000000000..66e7642c9b --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfFloatVectorAttribute.h @@ -0,0 +1,76 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2007, Weta Digital Ltd +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Weta Digital nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + + +#ifndef INCLUDED_IMF_FLOATVECTOR_ATTRIBUTE_H +#define INCLUDED_IMF_FLOATVECTOR_ATTRIBUTE_H + +//----------------------------------------------------------------------------- +// +// class FloatVectorAttribute +// +//----------------------------------------------------------------------------- + +#include "ImfAttribute.h" +#include "ImfNamespace.h" + +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +typedef std::vector + FloatVector; + +typedef TypedAttribute + FloatVectorAttribute; + +template <> +IMF_EXPORT +const char *FloatVectorAttribute::staticTypeName (); + +template <> +IMF_EXPORT +void FloatVectorAttribute::writeValueTo + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; + +template <> +IMF_EXPORT +void FloatVectorAttribute::readValueFrom + (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfForward.h b/3rdparty/openexr/IlmImf/ImfForward.h new file mode 100644 index 0000000000..ea51c24d8c --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfForward.h @@ -0,0 +1,127 @@ + + +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// Portions (c) 2012 Weta Digital Ltd +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMF_FORWARD_H +#define INCLUDED_IMF_FORWARD_H + +//////////////////////////////////////////////////////////////////// +// +// Forward declarations for OpenEXR - correctly declares namespace +// +//////////////////////////////////////////////////////////////////// + +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// classes for basic types; +template class Array; +template class Array2D; +struct Channel; +class ChannelList; +struct Chromaticities; + +// attributes used in headers are TypedAttributes +class Attribute; + +class Header; + +// file handling classes +class OutputFile; +class TiledInputFile; +class ScanLineInputFile; +class InputFile; +class TiledOutputFile; +class DeepScanLineInputFile; +class DeepScanLineOutputFile; +class DeepTiledInputFile; +class DeepTiledOutputFile; +class AcesInputFile; +class AcesOutputFile; +class TiledInputPart; +class TiledInputFile; +class TileOffsets; + +// multipart file handling +class GenericInputFile; +class GenericOutputFile; +class MultiPartInputFile; +class MultiPartOutputFile; + +class InputPart; +class TiledInputPart; +class DeepScanLineInputPart; +class DeepTiledInputPart; + +class OutputPart; +class ScanLineOutputPart; +class TiledOutputPart; +class DeepScanLineOutputPart; +class DeepTiledOutputPart; + + +// internal use only +struct InputPartData; +struct OutputStreamMutex; +struct OutputPartData; +struct InputStreamMutex; + +// frame buffers + +class FrameBuffer; +class DeepFrameBuffer; +struct DeepSlice; + +// compositing +class DeepCompositing; +class CompositeDeepScanLine; + +// preview image +class PreviewImage; +struct PreviewRgba; + +// streams +class OStream; +class IStream; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif // include guard diff --git a/3rdparty/openexr/IlmImf/ImfFrameBuffer.cpp b/3rdparty/openexr/IlmImf/ImfFrameBuffer.cpp index 24f88dbd4e..bced3b1686 100644 --- a/3rdparty/openexr/IlmImf/ImfFrameBuffer.cpp +++ b/3rdparty/openexr/IlmImf/ImfFrameBuffer.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -36,8 +36,8 @@ //----------------------------------------------------------------------------- // -// class Slice -// class FrameBuffer +// class Slice +// class FrameBuffer // //----------------------------------------------------------------------------- @@ -47,15 +47,17 @@ using namespace std; -namespace Imf { +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER Slice::Slice (PixelType t, - char *b, - size_t xst, - size_t yst, - int xsm, - int ysm, - double fv, + char *b, + size_t xst, + size_t yst, + int xsm, + int ysm, + double fv, bool xtc, bool ytc) : @@ -78,8 +80,8 @@ FrameBuffer::insert (const char name[], const Slice &slice) { if (name[0] == 0) { - THROW (Iex::ArgExc, - "Frame buffer slice name cannot be an empty string."); + THROW (IEX_NAMESPACE::ArgExc, + "Frame buffer slice name cannot be an empty string."); } _map[name] = slice; @@ -100,8 +102,8 @@ FrameBuffer::operator [] (const char name[]) if (i == _map.end()) { - THROW (Iex::ArgExc, - "Cannot find frame buffer slice \"" << name << "\"."); + THROW (IEX_NAMESPACE::ArgExc, + "Cannot find frame buffer slice \"" << name << "\"."); } return i->second; @@ -115,8 +117,8 @@ FrameBuffer::operator [] (const char name[]) const if (i == _map.end()) { - THROW (Iex::ArgExc, - "Cannot find frame buffer slice \"" << name << "\"."); + THROW (IEX_NAMESPACE::ArgExc, + "Cannot find frame buffer slice \"" << name << "\"."); } return i->second; @@ -223,4 +225,4 @@ FrameBuffer::find (const string &name) const } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfFrameBuffer.h b/3rdparty/openexr/IlmImf/ImfFrameBuffer.h index bada3ca28a..e7ef247220 100644 --- a/3rdparty/openexr/IlmImf/ImfFrameBuffer.h +++ b/3rdparty/openexr/IlmImf/ImfFrameBuffer.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,18 +39,21 @@ //----------------------------------------------------------------------------- // -// class Slice -// class FrameBuffer +// class Slice +// class FrameBuffer // //----------------------------------------------------------------------------- -#include -#include +#include "ImfName.h" +#include "ImfPixelType.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + #include #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER //------------------------------------------------------- @@ -68,43 +71,43 @@ struct Slice // Data type; see ImfPixelType.h //------------------------------ - PixelType type; + PixelType type; //--------------------------------------------------------------------- // Memory layout: The address of pixel (x, y) is // - // base + (xp / xSampling) * xStride + (yp / ySampling) * yStride + // base + (xp / xSampling) * xStride + (yp / ySampling) * yStride // // where xp and yp are computed as follows: // - // * If we are reading or writing a scanline-based file: + // * If we are reading or writing a scanline-based file: // - // xp = x - // yp = y + // xp = x + // yp = y // // * If we are reading a tile whose upper left coorner is at (xt, yt): // - // if xTileCoords is true then xp = x - xt, else xp = x - // if yTileCoords is true then yp = y - yt, else yp = y + // if xTileCoords is true then xp = x - xt, else xp = x + // if yTileCoords is true then yp = y - yt, else yp = y // //--------------------------------------------------------------------- - char * base; - size_t xStride; - size_t yStride; + char * base; + size_t xStride; + size_t yStride; //-------------------------------------------- // Subsampling: pixel (x, y) is present in the - // slice only if + // slice only if // // x % xSampling == 0 && y % ySampling == 0 // //-------------------------------------------- - int xSampling; - int ySampling; + int xSampling; + int ySampling; //---------------------------------------------------------- @@ -112,8 +115,8 @@ struct Slice // a channel that corresponds to this slice is read. //---------------------------------------------------------- - double fillValue; - + double fillValue; + //------------------------------------------------------- // For tiled files, the xTileCoords and yTileCoords flags @@ -135,13 +138,14 @@ struct Slice // Constructor //------------ + IMF_EXPORT Slice (PixelType type = HALF, - char * base = 0, - size_t xStride = 0, - size_t yStride = 0, - int xSampling = 1, - int ySampling = 1, - double fillValue = 0.0, + char * base = 0, + size_t xStride = 0, + size_t yStride = 0, + int xSampling = 1, + int ySampling = 1, + double fillValue = 0.0, bool xTileCoords = false, bool yTileCoords = false); }; @@ -155,35 +159,45 @@ class FrameBuffer // Add a slice //------------ - void insert (const char name[], - const Slice &slice); + IMF_EXPORT + void insert (const char name[], + const Slice &slice); - void insert (const std::string &name, - const Slice &slice); + IMF_EXPORT + void insert (const std::string &name, + const Slice &slice); //---------------------------------------------------------------- // Access to existing slices: // - // [n] Returns a reference to the slice with name n. - // If no slice with name n exists, an Iex::ArgExc - // is thrown. + // [n] Returns a reference to the slice with name n. + // If no slice with name n exists, an IEX_NAMESPACE::ArgExc + // is thrown. // - // findSlice(n) Returns a pointer to the slice with name n, - // or 0 if no slice with name n exists. + // findSlice(n) Returns a pointer to the slice with name n, + // or 0 if no slice with name n exists. // //---------------------------------------------------------------- - Slice & operator [] (const char name[]); - const Slice & operator [] (const char name[]) const; + IMF_EXPORT + Slice & operator [] (const char name[]); + IMF_EXPORT + const Slice & operator [] (const char name[]) const; - Slice & operator [] (const std::string &name); - const Slice & operator [] (const std::string &name) const; + IMF_EXPORT + Slice & operator [] (const std::string &name); + IMF_EXPORT + const Slice & operator [] (const std::string &name) const; - Slice * findSlice (const char name[]); - const Slice * findSlice (const char name[]) const; + IMF_EXPORT + Slice * findSlice (const char name[]); + IMF_EXPORT + const Slice * findSlice (const char name[]) const; - Slice * findSlice (const std::string &name); - const Slice * findSlice (const std::string &name) const; + IMF_EXPORT + Slice * findSlice (const std::string &name); + IMF_EXPORT + const Slice * findSlice (const std::string &name) const; //----------------------------------------- @@ -195,21 +209,29 @@ class FrameBuffer class Iterator; class ConstIterator; - Iterator begin (); - ConstIterator begin () const; + IMF_EXPORT + Iterator begin (); + IMF_EXPORT + ConstIterator begin () const; - Iterator end (); - ConstIterator end () const; + IMF_EXPORT + Iterator end (); + IMF_EXPORT + ConstIterator end () const; - Iterator find (const char name[]); - ConstIterator find (const char name[]) const; + IMF_EXPORT + Iterator find (const char name[]); + IMF_EXPORT + ConstIterator find (const char name[]) const; - Iterator find (const std::string &name); - ConstIterator find (const std::string &name) const; + IMF_EXPORT + Iterator find (const std::string &name); + IMF_EXPORT + ConstIterator find (const std::string &name) const; private: - SliceMap _map; + SliceMap _map; }; @@ -221,14 +243,20 @@ class FrameBuffer::Iterator { public: + IMF_EXPORT Iterator (); + IMF_EXPORT Iterator (const FrameBuffer::SliceMap::iterator &i); - Iterator & operator ++ (); - Iterator operator ++ (int); + IMF_EXPORT + Iterator & operator ++ (); + IMF_EXPORT + Iterator operator ++ (int); - const char * name () const; - Slice & slice () const; + IMF_EXPORT + const char * name () const; + IMF_EXPORT + Slice & slice () const; private: @@ -242,15 +270,22 @@ class FrameBuffer::ConstIterator { public: + IMF_EXPORT ConstIterator (); + IMF_EXPORT ConstIterator (const FrameBuffer::SliceMap::const_iterator &i); + IMF_EXPORT ConstIterator (const FrameBuffer::Iterator &other); - ConstIterator & operator ++ (); - ConstIterator operator ++ (int); + IMF_EXPORT + ConstIterator & operator ++ (); + IMF_EXPORT + ConstIterator operator ++ (int); - const char * name () const; - const Slice & slice () const; + IMF_EXPORT + const char * name () const; + IMF_EXPORT + const Slice & slice () const; private: @@ -364,7 +399,7 @@ FrameBuffer::ConstIterator::slice () const inline bool operator == (const FrameBuffer::ConstIterator &x, - const FrameBuffer::ConstIterator &y) + const FrameBuffer::ConstIterator &y) { return x._i == y._i; } @@ -372,12 +407,12 @@ operator == (const FrameBuffer::ConstIterator &x, inline bool operator != (const FrameBuffer::ConstIterator &x, - const FrameBuffer::ConstIterator &y) + const FrameBuffer::ConstIterator &y) { return !(x == y); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfFramesPerSecond.cpp b/3rdparty/openexr/IlmImf/ImfFramesPerSecond.cpp index e3874d9571..b56f9482a4 100644 --- a/3rdparty/openexr/IlmImf/ImfFramesPerSecond.cpp +++ b/3rdparty/openexr/IlmImf/ImfFramesPerSecond.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,9 +41,10 @@ #include #include "ImathFun.h" -using namespace Imath; +using namespace IMATH_NAMESPACE; +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER Rational guessExactFps (double fps) @@ -58,18 +59,18 @@ guessExactFps (const Rational &fps) const double e = 0.002; if (abs (double (fps) - double (fps_23_976())) < e) - return fps_23_976(); + return fps_23_976(); if (abs (double (fps) - double (fps_29_97())) < e) - return fps_29_97(); + return fps_29_97(); if (abs (double (fps) - double (fps_47_952())) < e) - return fps_47_952(); + return fps_47_952(); if (abs (double (fps) - double (fps_59_94())) < e) - return fps_59_94(); + return fps_59_94(); return fps; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfFramesPerSecond.h b/3rdparty/openexr/IlmImf/ImfFramesPerSecond.h index c950484078..59ab4cb20b 100644 --- a/3rdparty/openexr/IlmImf/ImfFramesPerSecond.h +++ b/3rdparty/openexr/IlmImf/ImfFramesPerSecond.h @@ -2,9 +2,9 @@ // // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -65,9 +65,13 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfRational.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { inline Rational fps_23_976 () {return Rational (24000, 1001);} inline Rational fps_24 () {return Rational (24, 1);} @@ -80,9 +84,11 @@ inline Rational fps_50 () {return Rational (50, 1);} inline Rational fps_59_94 () {return Rational (60000, 1001);} inline Rational fps_60 () {return Rational (60, 1);} -Rational guessExactFps (double fps); -Rational guessExactFps (const Rational &fps); +IMF_EXPORT Rational guessExactFps (double fps); +IMF_EXPORT Rational guessExactFps (const Rational &fps); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imf #endif diff --git a/3rdparty/openexr/IlmImf/ImfGenericInputFile.cpp b/3rdparty/openexr/IlmImf/ImfGenericInputFile.cpp new file mode 100644 index 0000000000..0096a0a9bb --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfGenericInputFile.cpp @@ -0,0 +1,76 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfGenericInputFile.h" + +#include +#include +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +void GenericInputFile::readMagicNumberAndVersionField(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, int& version) +{ + // + // Read the magic number and the file format version number. + // Then check if we can read the rest of this file. + // + + int magic; + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, magic); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, version); + + if (magic != MAGIC) + { + throw IEX_NAMESPACE::InputExc ("File is not an image file."); + } + + if (getVersion (version) != EXR_VERSION) + { + THROW (IEX_NAMESPACE::InputExc, "Cannot read " + "version " << getVersion (version) << " " + "image files. Current file format version " + "is " << EXR_VERSION << "."); + } + + if (!supportsFlags (getFlags (version))) + { + THROW (IEX_NAMESPACE::InputExc, "The file format version number's flag field " + "contains unrecognized flags."); + } +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfGenericInputFile.h b/3rdparty/openexr/IlmImf/ImfGenericInputFile.h new file mode 100644 index 0000000000..38cbcc2a85 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfGenericInputFile.h @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFGENERICINPUTFILE_H_ +#define IMFGENERICINPUTFILE_H_ + +#include "ImfIO.h" +#include "ImfHeader.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class GenericInputFile +{ + public: + IMF_EXPORT + virtual ~GenericInputFile() {} + + protected: + IMF_EXPORT + GenericInputFile() {} + IMF_EXPORT + void readMagicNumberAndVersionField(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, int& version); +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif /* IMFGENERICINPUTFILE_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfGenericOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfGenericOutputFile.cpp new file mode 100644 index 0000000000..8ec707b2f6 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfGenericOutputFile.cpp @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfGenericOutputFile.h" + +#include +#include +#include +#include + +#include +#include + +#include "ImfNamespace.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + + +using namespace std; + + + +void +GenericOutputFile::writeMagicNumberAndVersionField (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, + const Header& header) +{ + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, MAGIC); + + int version = EXR_VERSION; + + if (header.hasType() && isDeepData(header.type())) + { + version |= NON_IMAGE_FLAG; + } + else + { + // (TODO) we may want to check something else in function signature + // instead of hasTileDescription()? + if (header.hasTileDescription()) + version |= TILED_FLAG; + } + + if (usesLongNames (header)) + version |= LONG_NAMES_FLAG; + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, version); +} + +void +GenericOutputFile::writeMagicNumberAndVersionField (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, + const Header * headers, + int parts) +{ + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, MAGIC); + + int version = EXR_VERSION; + + if (parts == 1) + { + if (headers[0].type() == TILEDIMAGE) + version |= TILED_FLAG; + } + else + { + version |= MULTI_PART_FILE_FLAG; + } + + for (int i = 0; i < parts; i++) + { + if (usesLongNames (headers[i])) + version |= LONG_NAMES_FLAG; + + if (headers[i].hasType() && isImage(headers[i].type()) == false) + version |= NON_IMAGE_FLAG; + } + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, version); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfGenericOutputFile.h b/3rdparty/openexr/IlmImf/ImfGenericOutputFile.h new file mode 100644 index 0000000000..8980d36811 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfGenericOutputFile.h @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFGENERICOUTPUTFILE_H_ +#define IMFGENERICOUTPUTFILE_H_ + +#include "ImfVersion.h" +#include "ImfIO.h" +#include "ImfXdr.h" +#include "ImfHeader.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class GenericOutputFile +{ + public: + IMF_EXPORT + virtual ~GenericOutputFile() {} + + protected: + IMF_EXPORT + GenericOutputFile() {} + IMF_EXPORT + void writeMagicNumberAndVersionField (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, const Header& header); + IMF_EXPORT + void writeMagicNumberAndVersionField (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os, const Header * headers, int parts); + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* GENERICOUTPUTFILE_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfHeader.cpp b/3rdparty/openexr/IlmImf/ImfHeader.cpp index 394e8b3c84..d6b55f3c47 100644 --- a/3rdparty/openexr/IlmImf/ImfHeader.cpp +++ b/3rdparty/openexr/IlmImf/ImfHeader.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -49,9 +49,12 @@ #include #include #include +#include #include +#include #include #include +#include #include #include #include @@ -64,21 +67,23 @@ #include #include #include +#include #include "IlmThreadMutex.h" #include "Iex.h" #include #include #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER using namespace std; -using Imath::Box2i; -using Imath::V2i; -using Imath::V2f; -using IlmThread::Mutex; -using IlmThread::Lock; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::V2i; +using IMATH_NAMESPACE::V2f; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; namespace { @@ -91,13 +96,13 @@ int maxTileHeight = 0; void initialize (Header &header, - const Box2i &displayWindow, - const Box2i &dataWindow, - float pixelAspectRatio, - const V2f &screenWindowCenter, - float screenWindowWidth, - LineOrder lineOrder, - Compression compression) + const Box2i &displayWindow, + const Box2i &dataWindow, + float pixelAspectRatio, + const V2f &screenWindowCenter, + float screenWindowWidth, + LineOrder lineOrder, + Compression compression) { header.insert ("displayWindow", Box2iAttribute (displayWindow)); header.insert ("dataWindow", Box2iAttribute (dataWindow)); @@ -109,66 +114,29 @@ initialize (Header &header, header.insert ("channels", ChannelListAttribute ()); } - -bool -usesLongNames (const Header &header) -{ - // - // If an OpenEXR file contains any attribute names, attribute type names - // or channel names longer than 31 characters, then the file cannot be - // read by older versions of the IlmImf library (up to OpenEXR 1.6.1). - // Before writing the file header, we check if the header contains - // any names longer than 31 characters; if it does, then we set the - // LONG_NAMES_FLAG in the file version number. Older versions of the - // IlmImf library will refuse to read files that have the LONG_NAMES_FLAG - // set. Without the flag, older versions of the library would mis- - // interpret the file as broken. - // - - for (Header::ConstIterator i = header.begin(); - i != header.end(); - ++i) - { - if (strlen (i.name()) >= 32 || strlen (i.attribute().typeName()) >= 32) - return true; - } - - const ChannelList &channels = header.channels(); - - for (ChannelList::ConstIterator i = channels.begin(); - i != channels.end(); - ++i) - { - if (strlen (i.name()) >= 32) - return true; - } - - return false; -} - template void checkIsNullTerminated (const char (&str)[N], const char *what) { - for (int i = 0; i < N; ++i) { - if (str[i] == '\0') - return; - } - std::stringstream s; - s << "Invalid " << what << ": it is more than " << (N - 1) - << " characters long."; - throw Iex::InputExc(s); + for (size_t i = 0; i < N; ++i) { + if (str[i] == '\0') + return; + } + std::stringstream s; + s << "Invalid " << what << ": it is more than " << (N - 1) + << " characters long."; + throw IEX_NAMESPACE::InputExc(s); } } // namespace Header::Header (int width, - int height, - float pixelAspectRatio, - const V2f &screenWindowCenter, - float screenWindowWidth, - LineOrder lineOrder, - Compression compression) + int height, + float pixelAspectRatio, + const V2f &screenWindowCenter, + float screenWindowWidth, + LineOrder lineOrder, + Compression compression) : _map() { @@ -177,24 +145,24 @@ Header::Header (int width, Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1)); initialize (*this, - displayWindow, - displayWindow, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + displayWindow, + displayWindow, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); } Header::Header (int width, - int height, - const Box2i &dataWindow, - float pixelAspectRatio, - const V2f &screenWindowCenter, - float screenWindowWidth, - LineOrder lineOrder, - Compression compression) + int height, + const Box2i &dataWindow, + float pixelAspectRatio, + const V2f &screenWindowCenter, + float screenWindowWidth, + LineOrder lineOrder, + Compression compression) : _map() { @@ -203,46 +171,46 @@ Header::Header (int width, Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1)); initialize (*this, - displayWindow, - dataWindow, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + displayWindow, + dataWindow, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); } Header::Header (const Box2i &displayWindow, - const Box2i &dataWindow, - float pixelAspectRatio, - const V2f &screenWindowCenter, - float screenWindowWidth, - LineOrder lineOrder, - Compression compression) + const Box2i &dataWindow, + float pixelAspectRatio, + const V2f &screenWindowCenter, + float screenWindowWidth, + LineOrder lineOrder, + Compression compression) : _map() { staticInitialize(); initialize (*this, - displayWindow, - dataWindow, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + displayWindow, + dataWindow, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); } Header::Header (const Header &other): _map() { for (AttributeMap::const_iterator i = other._map.begin(); - i != other._map.end(); - ++i) + i != other._map.end(); + ++i) { - insert (*i->first, *i->second); + insert (*i->first, *i->second); } } @@ -250,73 +218,94 @@ Header::Header (const Header &other): _map() Header::~Header () { for (AttributeMap::iterator i = _map.begin(); - i != _map.end(); - ++i) + i != _map.end(); + ++i) { - delete i->second; + delete i->second; } } -Header & +Header & Header::operator = (const Header &other) { if (this != &other) { - for (AttributeMap::iterator i = _map.begin(); - i != _map.end(); - ++i) - { - delete i->second; + for (AttributeMap::iterator i = _map.begin(); + i != _map.end(); + ++i) + { + delete i->second; + } + + _map.erase (_map.begin(), _map.end()); + + for (AttributeMap::const_iterator i = other._map.begin(); + i != other._map.end(); + ++i) + { + insert (*i->first, *i->second); + } } - _map.erase (_map.begin(), _map.end()); + return *this; +} - for (AttributeMap::const_iterator i = other._map.begin(); - i != other._map.end(); - ++i) - { - insert (*i->first, *i->second); - } - } - return *this; +void +Header::erase (const char name[]) +{ + if (name[0] == 0) + THROW (IEX_NAMESPACE::ArgExc, "Image attribute name cannot be an empty string."); + + + AttributeMap::iterator i = _map.find (name); + if (i != _map.end()) + _map.erase (i); + } +void +Header::erase (const string &name) +{ + erase (name.c_str()); +} + + void Header::insert (const char name[], const Attribute &attribute) { if (name[0] == 0) - THROW (Iex::ArgExc, "Image attribute name cannot be an empty string."); + THROW (IEX_NAMESPACE::ArgExc, "Image attribute name cannot be an empty string."); AttributeMap::iterator i = _map.find (name); if (i == _map.end()) { - Attribute *tmp = attribute.copy(); - - try - { - _map[name] = tmp; - } - catch (...) - { - delete tmp; - throw; - } + Attribute *tmp = attribute.copy(); + + try + { + _map[name] = tmp; + } + catch (...) + { + delete tmp; + throw; + } } else { - if (strcmp (i->second->typeName(), attribute.typeName())) - THROW (Iex::TypeExc, "Cannot assign a value of " - "type \"" << attribute.typeName() << "\" " - "to image attribute \"" << name << "\" of " - "type \"" << i->second->typeName() << "\"."); - - Attribute *tmp = attribute.copy(); - delete i->second; - i->second = tmp; + if (strcmp (i->second->typeName(), attribute.typeName())) + THROW (IEX_NAMESPACE::TypeExc, "Cannot assign a value of " + "type \"" << attribute.typeName() << "\" " + "to image attribute \"" << name << "\" of " + "type \"" << i->second->typeName() << "\"."); + + Attribute *tmp = attribute.copy(); + delete i->second; + i->second = tmp; } } @@ -328,38 +317,38 @@ Header::insert (const string &name, const Attribute &attribute) } -Attribute & +Attribute & Header::operator [] (const char name[]) { AttributeMap::iterator i = _map.find (name); if (i == _map.end()) - THROW (Iex::ArgExc, "Cannot find image attribute \"" << name << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "Cannot find image attribute \"" << name << "\"."); return *i->second; } -const Attribute & +const Attribute & Header::operator [] (const char name[]) const { AttributeMap::const_iterator i = _map.find (name); if (i == _map.end()) - THROW (Iex::ArgExc, "Cannot find image attribute \"" << name << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "Cannot find image attribute \"" << name << "\"."); return *i->second; } -Attribute & +Attribute & Header::operator [] (const string &name) { return this->operator[] (name.c_str()); } -const Attribute & +const Attribute & Header::operator [] (const string &name) const { return this->operator[] (name.c_str()); @@ -422,99 +411,99 @@ Header::find (const string &name) const } -Imath::Box2i & +IMATH_NAMESPACE::Box2i & Header::displayWindow () { return static_cast - ((*this)["displayWindow"]).value(); + ((*this)["displayWindow"]).value(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & Header::displayWindow () const { return static_cast - ((*this)["displayWindow"]).value(); + ((*this)["displayWindow"]).value(); } -Imath::Box2i & +IMATH_NAMESPACE::Box2i & Header::dataWindow () { return static_cast - ((*this)["dataWindow"]).value(); + ((*this)["dataWindow"]).value(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & Header::dataWindow () const { return static_cast - ((*this)["dataWindow"]).value(); + ((*this)["dataWindow"]).value(); } -float & +float & Header::pixelAspectRatio () { return static_cast - ((*this)["pixelAspectRatio"]).value(); + ((*this)["pixelAspectRatio"]).value(); } -const float & +const float & Header::pixelAspectRatio () const { return static_cast - ((*this)["pixelAspectRatio"]).value(); + ((*this)["pixelAspectRatio"]).value(); } -Imath::V2f & +IMATH_NAMESPACE::V2f & Header::screenWindowCenter () { return static_cast - ((*this)["screenWindowCenter"]).value(); + ((*this)["screenWindowCenter"]).value(); } -const Imath::V2f & +const IMATH_NAMESPACE::V2f & Header::screenWindowCenter () const { return static_cast - ((*this)["screenWindowCenter"]).value(); + ((*this)["screenWindowCenter"]).value(); } -float & +float & Header::screenWindowWidth () { return static_cast - ((*this)["screenWindowWidth"]).value(); + ((*this)["screenWindowWidth"]).value(); } -const float & +const float & Header::screenWindowWidth () const { return static_cast - ((*this)["screenWindowWidth"]).value(); + ((*this)["screenWindowWidth"]).value(); } -ChannelList & +ChannelList & Header::channels () { return static_cast - ((*this)["channels"]).value(); + ((*this)["channels"]).value(); } -const ChannelList & +const ChannelList & Header::channels () const { return static_cast - ((*this)["channels"]).value(); + ((*this)["channels"]).value(); } @@ -522,7 +511,7 @@ LineOrder & Header::lineOrder () { return static_cast - ((*this)["lineOrder"]).value(); + ((*this)["lineOrder"]).value(); } @@ -530,7 +519,7 @@ const LineOrder & Header::lineOrder () const { return static_cast - ((*this)["lineOrder"]).value(); + ((*this)["lineOrder"]).value(); } @@ -538,7 +527,7 @@ Compression & Header::compression () { return static_cast - ((*this)["compression"]).value(); + ((*this)["compression"]).value(); } @@ -546,10 +535,166 @@ const Compression & Header::compression () const { return static_cast - ((*this)["compression"]).value(); + ((*this)["compression"]).value(); +} + + +void +Header::setName(const string& name) +{ + insert ("name", StringAttribute (name)); +} + + +bool +Header::hasName() const +{ + return findTypedAttribute ("name") != 0; +} + + +string & +Header::name() +{ + return typedAttribute ("name").value(); +} + + +const string & +Header::name() const +{ + return typedAttribute ("name").value(); +} + + +void +Header::setType(const string& type) +{ + if (isSupportedType(type) == false) + { + throw IEX_NAMESPACE::ArgExc (type + "is not a supported image type." + + "The following are supported: " + + SCANLINEIMAGE + ", " + + TILEDIMAGE + ", " + + DEEPSCANLINE + " or " + + DEEPTILE + "."); + } + + insert ("type", StringAttribute (type)); + + // (TODO) Should we do it here? + if (isDeepData(type) && hasVersion() == false) + { + setVersion(1); + } +} + + +bool +Header::hasType() const +{ + return findTypedAttribute ("type") != 0; +} + + +string & +Header::type() +{ + return typedAttribute ("type").value(); +} + + +const string & +Header::type() const +{ + return typedAttribute ("type").value(); } +void +Header::setView(const string& view) +{ + insert ("view", StringAttribute (view)); +} + + +bool +Header::hasView() const +{ + return findTypedAttribute ("view") != 0; +} + + +string & +Header::view() +{ + return typedAttribute ("view").value(); +} + + +const string & +Header::view() const +{ + return typedAttribute ("view").value(); +} + + +void +Header::setVersion(const int version) +{ + if (version != 1) + { + throw IEX_NAMESPACE::ArgExc ("We can only process version 1"); + } + + insert ("version", IntAttribute (version)); +} + + +bool +Header::hasVersion() const +{ + return findTypedAttribute ("version") != 0; +} + + +int & +Header::version() +{ + return typedAttribute ("version").value(); +} + + +const int & +Header::version() const +{ + return typedAttribute ("version").value(); +} + +void +Header::setChunkCount(int chunks) +{ + insert("chunkCount",IntAttribute(chunks)); +} + +bool +Header::hasChunkCount() const +{ + return findTypedAttribute("chunkCount") != 0; +} + +int& +Header::chunkCount() +{ + return typedAttribute ("chunkCount").value(); +} + +const int& +Header::chunkCount() const +{ + return typedAttribute ("chunkCount").value(); +} + void Header::setTileDescription(const TileDescription& td) { @@ -577,7 +722,7 @@ Header::tileDescription () const return typedAttribute ("tiles").value(); } -void +void Header::setPreviewImage (const PreviewImage &pi) { insert ("preview", PreviewImageAttribute (pi)); @@ -598,15 +743,15 @@ Header::previewImage () const } -bool +bool Header::hasPreviewImage () const { return findTypedAttribute ("preview") != 0; } -void -Header::sanityCheck (bool isTiled) const +void +Header::sanityCheck (bool isTiled, bool isMultipartFile) const { // // The display window and the data window must each @@ -619,41 +764,53 @@ Header::sanityCheck (bool isTiled) const const Box2i &displayWindow = this->displayWindow(); if (displayWindow.min.x > displayWindow.max.x || - displayWindow.min.y > displayWindow.max.y || - displayWindow.min.x <= -(INT_MAX / 2) || - displayWindow.min.y <= -(INT_MAX / 2) || - displayWindow.max.x >= (INT_MAX / 2) || - displayWindow.max.y >= (INT_MAX / 2)) + displayWindow.min.y > displayWindow.max.y || + displayWindow.min.x <= -(INT_MAX / 2) || + displayWindow.min.y <= -(INT_MAX / 2) || + displayWindow.max.x >= (INT_MAX / 2) || + displayWindow.max.y >= (INT_MAX / 2)) { - throw Iex::ArgExc ("Invalid display window in image header."); + throw IEX_NAMESPACE::ArgExc ("Invalid display window in image header."); } const Box2i &dataWindow = this->dataWindow(); if (dataWindow.min.x > dataWindow.max.x || - dataWindow.min.y > dataWindow.max.y || - dataWindow.min.x <= -(INT_MAX / 2) || - dataWindow.min.y <= -(INT_MAX / 2) || - dataWindow.max.x >= (INT_MAX / 2) || - dataWindow.max.y >= (INT_MAX / 2)) + dataWindow.min.y > dataWindow.max.y || + dataWindow.min.x <= -(INT_MAX / 2) || + dataWindow.min.y <= -(INT_MAX / 2) || + dataWindow.max.x >= (INT_MAX / 2) || + dataWindow.max.y >= (INT_MAX / 2)) { - throw Iex::ArgExc ("Invalid data window in image header."); + throw IEX_NAMESPACE::ArgExc ("Invalid data window in image header."); } if (maxImageWidth > 0 && - maxImageWidth < dataWindow.max.x - dataWindow.min.x + 1) + maxImageWidth < (dataWindow.max.x - dataWindow.min.x + 1)) { - THROW (Iex::ArgExc, "The width of the data window exceeds the " - "maximum width of " << maxImageWidth << "pixels."); + THROW (IEX_NAMESPACE::ArgExc, "The width of the data window exceeds the " + "maximum width of " << maxImageWidth << "pixels."); } if (maxImageHeight > 0 && - maxImageHeight < dataWindow.max.y - dataWindow.min.y + 1) + maxImageHeight < dataWindow.max.y - dataWindow.min.y + 1) { - THROW (Iex::ArgExc, "The width of the data window exceeds the " - "maximum width of " << maxImageHeight << "pixels."); + THROW (IEX_NAMESPACE::ArgExc, "The width of the data window exceeds the " + "maximum width of " << maxImageHeight << "pixels."); } + // chunk table must be smaller than the maximum image area + // (only reachable for unknown types or damaged files: will have thrown earlier + // for regular image types) + if( maxImageHeight>0 && maxImageWidth>0 && + hasChunkCount() && chunkCount()>Int64(maxImageWidth)*Int64(maxImageHeight)) + { + THROW (IEX_NAMESPACE::ArgExc, "chunkCount exceeds maximum area of " + << Int64(maxImageWidth)*Int64(maxImageHeight) << " pixels." ); + + } + + // // The pixel aspect ratio must be greater than 0. // In applications, numbers like the the display or @@ -671,9 +828,9 @@ Header::sanityCheck (bool isTiled) const const float MAX_PIXEL_ASPECT_RATIO = 1e+6f; if (pixelAspectRatio < MIN_PIXEL_ASPECT_RATIO || - pixelAspectRatio > MAX_PIXEL_ASPECT_RATIO) + pixelAspectRatio > MAX_PIXEL_ASPECT_RATIO) { - throw Iex::ArgExc ("Invalid pixel aspect ratio in image header."); + throw IEX_NAMESPACE::ArgExc ("Invalid pixel aspect ratio in image header."); } // @@ -687,63 +844,98 @@ Header::sanityCheck (bool isTiled) const float screenWindowWidth = this->screenWindowWidth(); if (screenWindowWidth < 0) - throw Iex::ArgExc ("Invalid screen window width in image header."); + throw IEX_NAMESPACE::ArgExc ("Invalid screen window width in image header."); // - // If the file is tiled, verify that the tile description has resonable - // values and check to see if the lineOrder is one of the predefined 3. - // If the file is not tiled, then the lineOrder can only be INCREASING_Y - // or DECREASING_Y. + // If the file has multiple parts, verify that each header has attribute + // name and type. + // (TODO) We may want to check more stuff here. // - LineOrder lineOrder = this->lineOrder(); - - if (isTiled) + if (isMultipartFile) { - if (!hasTileDescription()) - { - throw Iex::ArgExc ("Tiled image has no tile " - "description attribute."); - } - - const TileDescription &tileDesc = tileDescription(); + if (!hasName()) + { + throw IEX_NAMESPACE::ArgExc ("Headers in a multipart file should" + " have name attribute."); + } - if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0) - throw Iex::ArgExc ("Invalid tile size in image header."); + if (!hasType()) + { + throw IEX_NAMESPACE::ArgExc ("Headers in a multipart file should" + " have type attribute."); + } - if (maxTileWidth > 0 && - maxTileWidth < tileDesc.xSize) - { - THROW (Iex::ArgExc, "The width of the tiles exceeds the maximum " - "width of " << maxTileWidth << "pixels."); } - - if (maxTileHeight > 0 && - maxTileHeight < tileDesc.ySize) + + const std::string & part_type=hasType() ? type() : ""; + + if(part_type!="" && !isSupportedType(part_type)) { - THROW (Iex::ArgExc, "The width of the tiles exceeds the maximum " - "width of " << maxTileHeight << "pixels."); + // + // skip remaining sanity checks with unsupported types - they may not hold + // + return; } + + + // + // If the file is tiled, verify that the tile description has reasonable + // values and check to see if the lineOrder is one of the predefined 3. + // If the file is not tiled, then the lineOrder can only be INCREASING_Y + // or DECREASING_Y. + // - if (tileDesc.mode != ONE_LEVEL && - tileDesc.mode != MIPMAP_LEVELS && - tileDesc.mode != RIPMAP_LEVELS) - throw Iex::ArgExc ("Invalid level mode in image header."); - - if (tileDesc.roundingMode != ROUND_UP && - tileDesc.roundingMode != ROUND_DOWN) - throw Iex::ArgExc ("Invalid level rounding mode in image header."); + LineOrder lineOrder = this->lineOrder(); - if (lineOrder != INCREASING_Y && - lineOrder != DECREASING_Y && - lineOrder != RANDOM_Y) - throw Iex::ArgExc ("Invalid line order in image header."); + if (isTiled) + { + if (!hasTileDescription()) + { + throw IEX_NAMESPACE::ArgExc ("Tiled image has no tile " + "description attribute."); + } + + const TileDescription &tileDesc = tileDescription(); + + if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0) + throw IEX_NAMESPACE::ArgExc ("Invalid tile size in image header."); + + if (maxTileWidth > 0 && + maxTileWidth < int(tileDesc.xSize)) + { + THROW (IEX_NAMESPACE::ArgExc, "The width of the tiles exceeds the maximum " + "width of " << maxTileWidth << "pixels."); + } + + if (maxTileHeight > 0 && + maxTileHeight < int(tileDesc.ySize)) + { + THROW (IEX_NAMESPACE::ArgExc, "The width of the tiles exceeds the maximum " + "width of " << maxTileHeight << "pixels."); + } + + if (tileDesc.mode != ONE_LEVEL && + tileDesc.mode != MIPMAP_LEVELS && + tileDesc.mode != RIPMAP_LEVELS) + throw IEX_NAMESPACE::ArgExc ("Invalid level mode in image header."); + + if (tileDesc.roundingMode != ROUND_UP && + tileDesc.roundingMode != ROUND_DOWN) + throw IEX_NAMESPACE::ArgExc ("Invalid level rounding mode in image header."); + + if (lineOrder != INCREASING_Y && + lineOrder != DECREASING_Y && + lineOrder != RANDOM_Y) + throw IEX_NAMESPACE::ArgExc ("Invalid line order in image header."); } else { - if (lineOrder != INCREASING_Y && - lineOrder != DECREASING_Y) - throw Iex::ArgExc ("Invalid line order in image header."); + if (lineOrder != INCREASING_Y && + lineOrder != DECREASING_Y) + throw IEX_NAMESPACE::ArgExc ("Invalid line order in image header."); + + } // @@ -751,7 +943,13 @@ Header::sanityCheck (bool isTiled) const // if (!isValidCompression (this->compression())) - throw Iex::ArgExc ("Unknown compression type in image header."); + throw IEX_NAMESPACE::ArgExc ("Unknown compression type in image header."); + + if(isDeepData(part_type)) + { + if (!isValidDeepCompression (this->compression())) + throw IEX_NAMESPACE::ArgExc ("Compression type in header not valid for deep data"); + } // // Check the channel list: @@ -767,103 +965,103 @@ Header::sanityCheck (bool isTiled) const // const ChannelList &channels = this->channels(); - + if (isTiled) { - for (ChannelList::ConstIterator i = channels.begin(); - i != channels.end(); - ++i) - { - if (i.channel().type != UINT && - i.channel().type != HALF && - i.channel().type != FLOAT) - { - THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" " - "image channel is invalid."); - } - - if (i.channel().xSampling != 1) - { - THROW (Iex::ArgExc, "The x subsampling factor for the " - "\"" << i.name() << "\" channel " - "is not 1."); - } - - if (i.channel().ySampling != 1) - { - THROW (Iex::ArgExc, "The y subsampling factor for the " - "\"" << i.name() << "\" channel " - "is not 1."); - } - } + for (ChannelList::ConstIterator i = channels.begin(); + i != channels.end(); + ++i) + { + if (i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::UINT && + i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::HALF && + i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT) + { + THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" " + "image channel is invalid."); + } + + if (i.channel().xSampling != 1) + { + THROW (IEX_NAMESPACE::ArgExc, "The x subsampling factor for the " + "\"" << i.name() << "\" channel " + "is not 1."); + } + + if (i.channel().ySampling != 1) + { + THROW (IEX_NAMESPACE::ArgExc, "The y subsampling factor for the " + "\"" << i.name() << "\" channel " + "is not 1."); + } + } } else { - for (ChannelList::ConstIterator i = channels.begin(); - i != channels.end(); - ++i) - { - if (i.channel().type != UINT && - i.channel().type != HALF && - i.channel().type != FLOAT) - { - THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" " - "image channel is invalid."); - } - - if (i.channel().xSampling < 1) - { - THROW (Iex::ArgExc, "The x subsampling factor for the " - "\"" << i.name() << "\" channel " - "is invalid."); - } - - if (i.channel().ySampling < 1) - { - THROW (Iex::ArgExc, "The y subsampling factor for the " - "\"" << i.name() << "\" channel " - "is invalid."); - } - - if (dataWindow.min.x % i.channel().xSampling) - { - THROW (Iex::ArgExc, "The minimum x coordinate of the " - "image's data window is not a multiple " - "of the x subsampling factor of " - "the \"" << i.name() << "\" channel."); - } - - if (dataWindow.min.y % i.channel().ySampling) - { - THROW (Iex::ArgExc, "The minimum y coordinate of the " - "image's data window is not a multiple " - "of the y subsampling factor of " - "the \"" << i.name() << "\" channel."); - } - - if ((dataWindow.max.x - dataWindow.min.x + 1) % - i.channel().xSampling) - { - THROW (Iex::ArgExc, "Number of pixels per row in the " - "image's data window is not a multiple " - "of the x subsampling factor of " - "the \"" << i.name() << "\" channel."); - } - - if ((dataWindow.max.y - dataWindow.min.y + 1) % - i.channel().ySampling) - { - THROW (Iex::ArgExc, "Number of pixels per column in the " - "image's data window is not a multiple " - "of the y subsampling factor of " - "the \"" << i.name() << "\" channel."); - } - } + for (ChannelList::ConstIterator i = channels.begin(); + i != channels.end(); + ++i) + { + if (i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::UINT && + i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::HALF && + i.channel().type != OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT) + { + THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" " + "image channel is invalid."); + } + + if (i.channel().xSampling < 1) + { + THROW (IEX_NAMESPACE::ArgExc, "The x subsampling factor for the " + "\"" << i.name() << "\" channel " + "is invalid."); + } + + if (i.channel().ySampling < 1) + { + THROW (IEX_NAMESPACE::ArgExc, "The y subsampling factor for the " + "\"" << i.name() << "\" channel " + "is invalid."); + } + + if (dataWindow.min.x % i.channel().xSampling) + { + THROW (IEX_NAMESPACE::ArgExc, "The minimum x coordinate of the " + "image's data window is not a multiple " + "of the x subsampling factor of " + "the \"" << i.name() << "\" channel."); + } + + if (dataWindow.min.y % i.channel().ySampling) + { + THROW (IEX_NAMESPACE::ArgExc, "The minimum y coordinate of the " + "image's data window is not a multiple " + "of the y subsampling factor of " + "the \"" << i.name() << "\" channel."); + } + + if ((dataWindow.max.x - dataWindow.min.x + 1) % + i.channel().xSampling) + { + THROW (IEX_NAMESPACE::ArgExc, "Number of pixels per row in the " + "image's data window is not a multiple " + "of the x subsampling factor of " + "the \"" << i.name() << "\" channel."); + } + + if ((dataWindow.max.y - dataWindow.min.y + 1) % + i.channel().ySampling) + { + THROW (IEX_NAMESPACE::ArgExc, "Number of pixels per column in the " + "image's data window is not a multiple " + "of the y subsampling factor of " + "the \"" << i.name() << "\" channel."); + } + } } } -void +void Header::setMaxImageSize (int maxWidth, int maxHeight) { maxImageWidth = maxWidth; @@ -871,7 +1069,7 @@ Header::setMaxImageSize (int maxWidth, int maxHeight) } -void +void Header::setMaxTileSize (int maxWidth, int maxHeight) { maxTileWidth = maxWidth; @@ -879,26 +1077,23 @@ Header::setMaxTileSize (int maxWidth, int maxHeight) } +bool +Header::readsNothing() +{ + return _readsNothing; +} + + Int64 -Header::writeTo (OStream &os, bool isTiled) const +Header::writeTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, bool isTiled) const { // // Write a "magic number" to identify the file as an image file. // Write the current file format version number. // - Xdr::write (os, MAGIC); - int version = EXR_VERSION; - if (isTiled) - version |= TILED_FLAG; - - if (usesLongNames (*this)) - version |= LONG_NAMES_FLAG; - - Xdr::write (os, version); - // // Write all attributes. If we have a preview image attribute, // keep track of its position in the file. @@ -907,150 +1102,129 @@ Header::writeTo (OStream &os, bool isTiled) const Int64 previewPosition = 0; const Attribute *preview = - findTypedAttribute ("preview"); + findTypedAttribute ("preview"); for (ConstIterator i = begin(); i != end(); ++i) { - // - // Write the attribute's name and type. - // + // + // Write the attribute's name and type. + // - Xdr::write (os, i.name()); - Xdr::write (os, i.attribute().typeName()); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, i.name()); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, i.attribute().typeName()); - // - // Write the size of the attribute value, - // and the value itself. - // + // + // Write the size of the attribute value, + // and the value itself. + // - StdOSStream oss; - i.attribute().writeValueTo (oss, version); + StdOSStream oss; + i.attribute().writeValueTo (oss, version); - std::string s = oss.str(); - Xdr::write (os, (int) s.length()); + std::string s = oss.str(); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, (int) s.length()); - if (&i.attribute() == preview) - previewPosition = os.tellp(); + if (&i.attribute() == preview) + previewPosition = os.tellp(); - os.write (s.data(), s.length()); + os.write (s.data(), int(s.length())); } // // Write zero-length attribute name to mark the end of the header. // - Xdr::write (os, ""); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, ""); return previewPosition; } void -Header::readFrom (IStream &is, int &version) +Header::readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int &version) { - // - // Read the magic number and the file format version number. - // Then check if we can read the rest of this file. - // - - int magic; - - Xdr::read (is, magic); - Xdr::read (is, version); - - if (magic != MAGIC) - { - throw Iex::InputExc ("File is not an image file."); - } - - if (getVersion (version) != EXR_VERSION) - { - THROW (Iex::InputExc, "Cannot read " - "version " << getVersion (version) << " " - "image files. Current file format version " - "is " << EXR_VERSION << "."); - } - - if (!supportsFlags (getFlags (version))) - { - THROW (Iex::InputExc, "The file format version number's flag field " - "contains unrecognized flags."); - } - // // Read all attributes. // - while (true) - { - // - // Read the name of the attribute. - // A zero-length attribute name indicates the end of the header. - // - - char name[Name::SIZE]; - Xdr::read (is, Name::MAX_LENGTH, name); - - if (name[0] == 0) - break; - - checkIsNullTerminated (name, "attribute name"); - - // - // Read the attribute type and the size of the attribute value. - // - - char typeName[Name::SIZE]; - int size; - - Xdr::read (is, Name::MAX_LENGTH, typeName); - checkIsNullTerminated (typeName, "attribute type name"); - Xdr::read (is, size); - - AttributeMap::iterator i = _map.find (name); - - if (i != _map.end()) - { - // - // The attribute already exists (for example, - // because it is a predefined attribute). - // Read the attribute's new value from the file. - // - - if (strncmp (i->second->typeName(), typeName, sizeof (typeName))) - THROW (Iex::InputExc, "Unexpected type for image attribute " - "\"" << name << "\"."); + int attrCount = 0; - i->second->readValueFrom (is, size, version); - } - else + while (true) { - // - // The new attribute does not exist yet. - // If the attribute type is of a known type, - // read the attribute value. If the attribute - // is of an unknown type, read its value and - // store it as an OpaqueAttribute. - // - - Attribute *attr; - - if (Attribute::knownType (typeName)) - attr = Attribute::newAttribute (typeName); - else - attr = new OpaqueAttribute (typeName); - - try - { - attr->readValueFrom (is, size, version); - _map[name] = attr; - } - catch (...) - { - delete attr; - throw; - } - } + // + // Read the name of the attribute. + // A zero-length attribute name indicates the end of the header. + // + + char name[Name::SIZE]; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, Name::MAX_LENGTH, name); + + if (name[0] == 0) + { + if (attrCount == 0) _readsNothing = true; + else _readsNothing = false; + break; + } + + attrCount++; + + checkIsNullTerminated (name, "attribute name"); + + // + // Read the attribute type and the size of the attribute value. + // + + char typeName[Name::SIZE]; + int size; + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, Name::MAX_LENGTH, typeName); + checkIsNullTerminated (typeName, "attribute type name"); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, size); + + AttributeMap::iterator i = _map.find (name); + + if (i != _map.end()) + { + // + // The attribute already exists (for example, + // because it is a predefined attribute). + // Read the attribute's new value from the file. + // + + if (strncmp (i->second->typeName(), typeName, sizeof (typeName))) + THROW (IEX_NAMESPACE::InputExc, "Unexpected type for image attribute " + "\"" << name << "\"."); + + i->second->readValueFrom (is, size, version); + } + else + { + // + // The new attribute does not exist yet. + // If the attribute type is of a known type, + // read the attribute value. If the attribute + // is of an unknown type, read its value and + // store it as an OpaqueAttribute. + // + + Attribute *attr; + + if (Attribute::knownType (typeName)) + attr = Attribute::newAttribute (typeName); + else + attr = new OpaqueAttribute (typeName); + + try + { + attr->readValueFrom (is, size, version); + _map[name] = attr; + } + catch (...) + { + delete attr; + throw; + } + } } } @@ -1065,42 +1239,45 @@ staticInitialize () if (!initialized) { - // - // One-time initialization -- register - // some predefined attribute types. - // - - Box2fAttribute::registerAttributeType(); - Box2iAttribute::registerAttributeType(); - ChannelListAttribute::registerAttributeType(); - CompressionAttribute::registerAttributeType(); - ChromaticitiesAttribute::registerAttributeType(); - DoubleAttribute::registerAttributeType(); - EnvmapAttribute::registerAttributeType(); - FloatAttribute::registerAttributeType(); - IntAttribute::registerAttributeType(); - KeyCodeAttribute::registerAttributeType(); - LineOrderAttribute::registerAttributeType(); - M33dAttribute::registerAttributeType(); - M33fAttribute::registerAttributeType(); - M44dAttribute::registerAttributeType(); - M44fAttribute::registerAttributeType(); - PreviewImageAttribute::registerAttributeType(); - RationalAttribute::registerAttributeType(); - StringAttribute::registerAttributeType(); + // + // One-time initialization -- register + // some predefined attribute types. + // + + Box2fAttribute::registerAttributeType(); + Box2iAttribute::registerAttributeType(); + ChannelListAttribute::registerAttributeType(); + CompressionAttribute::registerAttributeType(); + ChromaticitiesAttribute::registerAttributeType(); + DeepImageStateAttribute::registerAttributeType(); + DoubleAttribute::registerAttributeType(); + EnvmapAttribute::registerAttributeType(); + FloatAttribute::registerAttributeType(); + FloatVectorAttribute::registerAttributeType(); + IntAttribute::registerAttributeType(); + KeyCodeAttribute::registerAttributeType(); + LineOrderAttribute::registerAttributeType(); + M33dAttribute::registerAttributeType(); + M33fAttribute::registerAttributeType(); + M44dAttribute::registerAttributeType(); + M44fAttribute::registerAttributeType(); + PreviewImageAttribute::registerAttributeType(); + RationalAttribute::registerAttributeType(); + StringAttribute::registerAttributeType(); StringVectorAttribute::registerAttributeType(); - TileDescriptionAttribute::registerAttributeType(); - TimeCodeAttribute::registerAttributeType(); - V2dAttribute::registerAttributeType(); - V2fAttribute::registerAttributeType(); - V2iAttribute::registerAttributeType(); - V3dAttribute::registerAttributeType(); - V3fAttribute::registerAttributeType(); - V3iAttribute::registerAttributeType(); - - initialized = true; + TileDescriptionAttribute::registerAttributeType(); + TimeCodeAttribute::registerAttributeType(); + V2dAttribute::registerAttributeType(); + V2fAttribute::registerAttributeType(); + V2iAttribute::registerAttributeType(); + V3dAttribute::registerAttributeType(); + V3fAttribute::registerAttributeType(); + V3iAttribute::registerAttributeType(); + DwaCompressor::initializeFuncs(); + + initialized = true; } } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfHeader.h b/3rdparty/openexr/IlmImf/ImfHeader.h index 8b83829656..638d298cfa 100644 --- a/3rdparty/openexr/IlmImf/ImfHeader.h +++ b/3rdparty/openexr/IlmImf/ImfHeader.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,44 +43,46 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include +#include "ImfLineOrder.h" +#include "ImfCompression.h" +#include "ImfName.h" +#include "ImfTileDescription.h" +#include "ImfInt64.h" #include "ImathVec.h" #include "ImathBox.h" #include "IexBaseExc.h" + +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + #include #include #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -class Attribute; -class ChannelList; -class IStream; -class OStream; -class PreviewImage; +using std::string; class Header { public: - + //---------------------------------------------------------------- // Default constructor -- the display window and the data window // are both set to Box2i (V2i (0, 0), V2i (width-1, height-1). //---------------------------------------------------------------- + IMF_EXPORT Header (int width = 64, - int height = 64, - float pixelAspectRatio = 1, - const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression = ZIP_COMPRESSION); + int height = 64, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression = ZIP_COMPRESSION); //-------------------------------------------------------------------- @@ -88,14 +90,15 @@ class Header // window is set to Box2i (V2i (0, 0), V2i (width-1, height-1). //-------------------------------------------------------------------- + IMF_EXPORT Header (int width, - int height, - const Imath::Box2i &dataWindow, - float pixelAspectRatio = 1, - const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression = ZIP_COMPRESSION); + int height, + const IMATH_NAMESPACE::Box2i &dataWindow, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression = ZIP_COMPRESSION); //---------------------------------------------------------- @@ -103,19 +106,21 @@ class Header // both specified explicitly. //---------------------------------------------------------- - Header (const Imath::Box2i &displayWindow, - const Imath::Box2i &dataWindow, - float pixelAspectRatio = 1, - const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression = ZIP_COMPRESSION); + IMF_EXPORT + Header (const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f &screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression = ZIP_COMPRESSION); //----------------- // Copy constructor //----------------- + IMF_EXPORT Header (const Header &other); @@ -123,6 +128,7 @@ class Header // Destructor //----------- + IMF_EXPORT ~Header (); @@ -130,6 +136,7 @@ class Header // Assignment //----------- + IMF_EXPORT Header & operator = (const Header &other); @@ -146,30 +153,50 @@ class Header // is copied into this attribute. // // If an attribute with name n exists, and its - // type is different from attr, an Iex::TypeExc + // type is different from attr, an IEX_NAMESPACE::TypeExc // is thrown. // //--------------------------------------------------------------- + IMF_EXPORT void insert (const char name[], - const Attribute &attribute); + const Attribute &attribute); + IMF_EXPORT void insert (const std::string &name, - const Attribute &attribute); + const Attribute &attribute); + + //--------------------------------------------------------------- + // Remove an attribute: + // + // remove(n) If an attribute with name n exists, then it + // is removed from the map of present attributes. + // + // If no attribute with name n exists, then this + // functions becomes a 'no-op' + // + //--------------------------------------------------------------- + IMF_EXPORT + void erase (const char name[]); + IMF_EXPORT + void erase (const std::string &name); + + + //------------------------------------------------------------------ // Access to existing attributes: // // [n] Returns a reference to the attribute // with name n. If no attribute with - // name n exists, an Iex::ArgExc is thrown. + // name n exists, an IEX_NAMESPACE::ArgExc is thrown. // // typedAttribute(n) Returns a reference to the attribute // with name n and type T. If no attribute - // with name n exists, an Iex::ArgExc is + // with name n exists, an IEX_NAMESPACE::ArgExc is // thrown. If an attribute with name n // exists, but its type is not T, an - // Iex::TypeExc is thrown. + // IEX_NAMESPACE::TypeExc is thrown. // // findTypedAttribute(n) Returns a pointer to the attribute with // name n and type T, or 0 if no attribute @@ -177,10 +204,14 @@ class Header // //------------------------------------------------------------------ + IMF_EXPORT Attribute & operator [] (const char name[]); + IMF_EXPORT const Attribute & operator [] (const char name[]) const; + IMF_EXPORT Attribute & operator [] (const std::string &name); + IMF_EXPORT const Attribute & operator [] (const std::string &name) const; template T& typedAttribute (const char name[]); @@ -194,7 +225,7 @@ class Header template T* findTypedAttribute (const std::string &name); template const T* findTypedAttribute (const std::string &name) - const; + const; //--------------------------------------------- // Iterator-style access to existing attributes @@ -205,16 +236,24 @@ class Header class Iterator; class ConstIterator; + IMF_EXPORT Iterator begin (); + IMF_EXPORT ConstIterator begin () const; + IMF_EXPORT Iterator end (); + IMF_EXPORT ConstIterator end () const; + IMF_EXPORT Iterator find (const char name[]); + IMF_EXPORT ConstIterator find (const char name[]) const; + IMF_EXPORT Iterator find (const std::string &name); + IMF_EXPORT ConstIterator find (const std::string &name) const; @@ -222,31 +261,113 @@ class Header // Access to predefined attributes //-------------------------------- - Imath::Box2i & displayWindow (); - const Imath::Box2i & displayWindow () const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i & displayWindow (); + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & displayWindow () const; - Imath::Box2i & dataWindow (); - const Imath::Box2i & dataWindow () const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i & dataWindow (); + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & dataWindow () const; + IMF_EXPORT float & pixelAspectRatio (); + IMF_EXPORT const float & pixelAspectRatio () const; - Imath::V2f & screenWindowCenter (); - const Imath::V2f & screenWindowCenter () const; + IMF_EXPORT + IMATH_NAMESPACE::V2f & screenWindowCenter (); + IMF_EXPORT + const IMATH_NAMESPACE::V2f & screenWindowCenter () const; + IMF_EXPORT float & screenWindowWidth (); + IMF_EXPORT const float & screenWindowWidth () const; + IMF_EXPORT ChannelList & channels (); + IMF_EXPORT const ChannelList & channels () const; + IMF_EXPORT LineOrder & lineOrder (); + IMF_EXPORT const LineOrder & lineOrder () const; + IMF_EXPORT Compression & compression (); + IMF_EXPORT const Compression & compression () const; + //----------------------------------------------------- + // Access to required attributes for multipart files + // They are optional to non-multipart files and mandatory + // for multipart files. + //----------------------------------------------------- + IMF_EXPORT + void setName (const string& name); + + IMF_EXPORT + string& name(); + IMF_EXPORT + const string& name() const; + + IMF_EXPORT + bool hasName() const; + + IMF_EXPORT + void setType (const string& Type); + + IMF_EXPORT + string& type(); + IMF_EXPORT + const string& type() const; + + IMF_EXPORT + bool hasType() const; + + IMF_EXPORT + void setVersion (const int version); + + IMF_EXPORT + int& version(); + IMF_EXPORT + const int& version() const; + + IMF_EXPORT + bool hasVersion() const; + + // + // the chunkCount attribute is set automatically when a file is written. + // There is no need to set it manually + // + IMF_EXPORT + void setChunkCount(int chunks); + IMF_EXPORT + bool hasChunkCount() const; + IMF_EXPORT + const int & chunkCount() const; + IMF_EXPORT + int & chunkCount(); + + + // + // for multipart files, return whether the file has a view string attribute + // (for the deprecated single part multiview format EXR, see ImfMultiView.h) + // + IMF_EXPORT + void setView(const string & view); + IMF_EXPORT + bool hasView() const; + IMF_EXPORT + string & view(); + IMF_EXPORT + const string & view() const; + + //---------------------------------------------------------------------- // Tile Description: // @@ -268,11 +389,15 @@ class Header // //---------------------------------------------------------------------- + IMF_EXPORT void setTileDescription (const TileDescription & td); + IMF_EXPORT TileDescription & tileDescription (); + IMF_EXPORT const TileDescription & tileDescription () const; + IMF_EXPORT bool hasTileDescription() const; @@ -297,11 +422,15 @@ class Header // //---------------------------------------------------------------------- + IMF_EXPORT void setPreviewImage (const PreviewImage &p); + IMF_EXPORT PreviewImage & previewImage (); + IMF_EXPORT const PreviewImage & previewImage () const; + IMF_EXPORT bool hasPreviewImage () const; @@ -314,7 +443,9 @@ class Header // header //------------------------------------------------------------- - void sanityCheck (bool isTiled = false) const; + IMF_EXPORT + void sanityCheck (bool isTiled = false, + bool isMultipartFile = false) const; //---------------------------------------------------------------- @@ -323,7 +454,7 @@ class Header // sanityCheck() will throw an exception if the width or height of // the data window exceeds the maximum image width or height, or // if the size of a tile exceeds the maximum tile width or height. - // + // // At program startup the maximum image and tile width and height // are set to zero, meaning that width and height are unlimited. // @@ -333,9 +464,17 @@ class Header // a damaged image file. //---------------------------------------------------------------- + IMF_EXPORT static void setMaxImageSize (int maxWidth, int maxHeight); + IMF_EXPORT static void setMaxTileSize (int maxWidth, int maxHeight); + // + // Check if the header reads nothing. + // + IMF_EXPORT + bool readsNothing(); + //------------------------------------------------------------------ // Input and output: @@ -348,14 +487,20 @@ class Header //------------------------------------------------------------------ - Int64 writeTo (OStream &os, - bool isTiled = false) const; + IMF_EXPORT + Int64 writeTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + bool isTiled = false) const; - void readFrom (IStream &is, int &version); + IMF_EXPORT + void readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int &version); + private: AttributeMap _map; + + bool _readsNothing; }; @@ -367,13 +512,19 @@ class Header::Iterator { public: + IMF_EXPORT Iterator (); + IMF_EXPORT Iterator (const Header::AttributeMap::iterator &i); + IMF_EXPORT Iterator & operator ++ (); + IMF_EXPORT Iterator operator ++ (int); + IMF_EXPORT const char * name () const; + IMF_EXPORT Attribute & attribute () const; private: @@ -388,14 +539,21 @@ class Header::ConstIterator { public: + IMF_EXPORT ConstIterator (); + IMF_EXPORT ConstIterator (const Header::AttributeMap::const_iterator &i); + IMF_EXPORT ConstIterator (const Header::Iterator &other); + IMF_EXPORT ConstIterator & operator ++ (); + IMF_EXPORT ConstIterator operator ++ (int); + IMF_EXPORT const char * name () const; + IMF_EXPORT const Attribute & attribute () const; private: @@ -421,7 +579,7 @@ class Header::ConstIterator // //------------------------------------------------------------------------ -void staticInitialize (); +void IMF_EXPORT staticInitialize (); //----------------- @@ -443,7 +601,7 @@ Header::Iterator::Iterator (const Header::AttributeMap::iterator &i): _i (i) } -inline Header::Iterator & +inline Header::Iterator & Header::Iterator::operator ++ () { ++_i; @@ -451,7 +609,7 @@ Header::Iterator::operator ++ () } -inline Header::Iterator +inline Header::Iterator Header::Iterator::operator ++ (int) { Iterator tmp = *this; @@ -467,7 +625,7 @@ Header::Iterator::name () const } -inline Attribute & +inline Attribute & Header::Iterator::attribute () const { return *_i->second; @@ -503,7 +661,7 @@ Header::ConstIterator::operator ++ () } -inline Header::ConstIterator +inline Header::ConstIterator Header::ConstIterator::operator ++ (int) { ConstIterator tmp = *this; @@ -519,7 +677,7 @@ Header::ConstIterator::name () const } -inline const Attribute & +inline const Attribute & Header::ConstIterator::attribute () const { return *_i->second; @@ -552,7 +710,7 @@ Header::typedAttribute (const char name[]) T *tattr = dynamic_cast (attr); if (tattr == 0) - throw Iex::TypeExc ("Unexpected attribute type."); + throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); return *tattr; } @@ -566,7 +724,7 @@ Header::typedAttribute (const char name[]) const const T *tattr = dynamic_cast (attr); if (tattr == 0) - throw Iex::TypeExc ("Unexpected attribute type."); + throw IEX_NAMESPACE::TypeExc ("Unexpected attribute type."); return *tattr; } @@ -622,6 +780,6 @@ Header::findTypedAttribute (const std::string &name) const } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfHuf.cpp b/3rdparty/openexr/IlmImf/ImfHuf.cpp index 3450f11e86..97909a5b19 100644 --- a/3rdparty/openexr/IlmImf/ImfHuf.cpp +++ b/3rdparty/openexr/IlmImf/ImfHuf.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -47,17 +47,20 @@ #include #include -#include +#include "ImfAutoArray.h" +#include "ImfFastHuf.h" #include "Iex.h" -#include -#include +#include +#include #include using namespace std; -using namespace Iex; +using namespace IEX_NAMESPACE; +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { namespace { @@ -71,10 +74,10 @@ const int HUF_DECMASK = HUF_DECSIZE - 1; struct HufDec { // short code long code - //------------------------------- - int len:8; // code length 0 - int lit:24; // lit p size - int * p; // 0 lits + //------------------------------- + int len:8; // code length 0 + int lit:24; // lit p size + int * p; // 0 lits }; @@ -82,7 +85,7 @@ void invalidNBits () { throw InputExc ("Error in header for Huffman-encoded data " - "(invalid number of bits)."); + "(invalid number of bits)."); } @@ -90,7 +93,7 @@ void tooMuchData () { throw InputExc ("Error in Huffman-encoded data " - "(decoded data are longer than expected)."); + "(decoded data are longer than expected)."); } @@ -98,7 +101,7 @@ void notEnoughData () { throw InputExc ("Error in Huffman-encoded data " - "(decoded data are shorter than expected)."); + "(decoded data are shorter than expected)."); } @@ -106,7 +109,7 @@ void invalidCode () { throw InputExc ("Error in Huffman-encoded data " - "(invalid code)."); + "(invalid code)."); } @@ -114,7 +117,7 @@ void invalidTableSize () { throw InputExc ("Error in Huffman-encoded data " - "(invalid code table size)."); + "(invalid code table size)."); } @@ -122,7 +125,7 @@ void unexpectedEndOfTable () { throw InputExc ("Error in Huffman-encoded data " - "(unexpected end of code table data)."); + "(unexpected end of code table data)."); } @@ -130,7 +133,7 @@ void tableTooLong () { throw InputExc ("Error in Huffman-encoded data " - "(code table is longer than expected)."); + "(code table is longer than expected)."); } @@ -138,7 +141,7 @@ void invalidTableEntry () { throw InputExc ("Error in Huffman-encoded data " - "(invalid code table entry)."); + "(invalid code table entry)."); } @@ -165,7 +168,7 @@ outputBits (int nBits, Int64 bits, Int64 &c, int &lc, char *&out) c |= bits; while (lc >= 8) - *out++ = (c >> (lc -= 8)); + *out++ = (c >> (lc -= 8)); } @@ -174,8 +177,8 @@ getBits (int nBits, Int64 &c, int &lc, const char *&in) { while (lc < nBits) { - c = (c << 8) | *(unsigned char *)(in++); - lc += 8; + c = (c << 8) | *(unsigned char *)(in++); + lc += 8; } lc -= nBits; @@ -215,10 +218,10 @@ hufCanonicalCodeTable (Int64 hcode[HUF_ENCSIZE]) // for (int i = 0; i <= 58; ++i) - n[i] = 0; + n[i] = 0; for (int i = 0; i < HUF_ENCSIZE; ++i) - n[hcode[i]] += 1; + n[hcode[i]] += 1; // // For each i from 58 through 1, compute the @@ -230,9 +233,9 @@ hufCanonicalCodeTable (Int64 hcode[HUF_ENCSIZE]) for (int i = 58; i > 0; --i) { - Int64 nc = ((c + n[i]) >> 1); - n[i] = c; - c = nc; + Int64 nc = ((c + n[i]) >> 1); + n[i] = c; + c = nc; } // @@ -244,10 +247,10 @@ hufCanonicalCodeTable (Int64 hcode[HUF_ENCSIZE]) for (int i = 0; i < HUF_ENCSIZE; ++i) { - int l = hcode[i]; + int l = hcode[i]; - if (l > 0) - hcode[i] = l | (n[l]++ << 6); + if (l > 0) + hcode[i] = l | (n[l]++ << 6); } } @@ -301,20 +304,20 @@ hufBuildEncTable *im = 0; while (!frq[*im]) - (*im)++; + (*im)++; int nf = 0; for (int i = *im; i < HUF_ENCSIZE; i++) { - hlink[i] = i; - - if (frq[i]) - { - fHeap[nf] = &frq[i]; - nf++; - *iM = i; - } + hlink[i] = i; + + if (frq[i]) + { + fHeap[nf] = &frq[i]; + nf++; + *iM = i; + } } // @@ -363,71 +366,71 @@ hufBuildEncTable while (nf > 1) { - // - // Find the indices, mm and m, of the two smallest non-zero frq - // values in fHeap, add the smallest frq to the second-smallest - // frq, and remove the smallest frq value from fHeap. - // - - int mm = fHeap[0] - frq; - pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare()); - --nf; - - int m = fHeap[0] - frq; - pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare()); - - frq[m ] += frq[mm]; - push_heap (&fHeap[0], &fHeap[nf], FHeapCompare()); - - // - // The entries in scode are linked into lists with the - // entries in hlink serving as "next" pointers and with - // the end of a list marked by hlink[j] == j. - // - // Traverse the lists that start at scode[m] and scode[mm]. - // For each element visited, increment the length of the - // corresponding code by one bit. (If we visit scode[j] - // during the traversal, then the code for symbol j becomes - // one bit longer.) - // - // Merge the lists that start at scode[m] and scode[mm] - // into a single list that starts at scode[m]. - // - - // - // Add a bit to all codes in the first list. - // - - for (int j = m; true; j = hlink[j]) - { - scode[j]++; - - assert (scode[j] <= 58); - - if (hlink[j] == j) - { - // - // Merge the two lists. - // - - hlink[j] = mm; - break; - } - } - - // - // Add a bit to all codes in the second list - // - - for (int j = mm; true; j = hlink[j]) - { - scode[j]++; - - assert (scode[j] <= 58); - - if (hlink[j] == j) - break; - } + // + // Find the indices, mm and m, of the two smallest non-zero frq + // values in fHeap, add the smallest frq to the second-smallest + // frq, and remove the smallest frq value from fHeap. + // + + int mm = fHeap[0] - frq; + pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare()); + --nf; + + int m = fHeap[0] - frq; + pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare()); + + frq[m ] += frq[mm]; + push_heap (&fHeap[0], &fHeap[nf], FHeapCompare()); + + // + // The entries in scode are linked into lists with the + // entries in hlink serving as "next" pointers and with + // the end of a list marked by hlink[j] == j. + // + // Traverse the lists that start at scode[m] and scode[mm]. + // For each element visited, increment the length of the + // corresponding code by one bit. (If we visit scode[j] + // during the traversal, then the code for symbol j becomes + // one bit longer.) + // + // Merge the lists that start at scode[m] and scode[mm] + // into a single list that starts at scode[m]. + // + + // + // Add a bit to all codes in the first list. + // + + for (int j = m; true; j = hlink[j]) + { + scode[j]++; + + assert (scode[j] <= 58); + + if (hlink[j] == j) + { + // + // Merge the two lists. + // + + hlink[j] = mm; + break; + } + } + + // + // Add a bit to all codes in the second list + // + + for (int j = mm; true; j = hlink[j]) + { + scode[j]++; + + assert (scode[j] <= 58); + + if (hlink[j] == j) + break; + } } // @@ -475,40 +478,40 @@ hufPackEncTable for (; im <= iM; im++) { - int l = hufLength (hcode[im]); - - if (l == 0) - { - int zerun = 1; - - while ((im < iM) && (zerun < LONGEST_LONG_RUN)) - { - if (hufLength (hcode[im+1]) > 0 ) - break; - im++; - zerun++; - } - - if (zerun >= 2) - { - if (zerun >= SHORTEST_LONG_RUN) - { - outputBits (6, LONG_ZEROCODE_RUN, c, lc, p); - outputBits (8, zerun - SHORTEST_LONG_RUN, c, lc, p); - } - else - { - outputBits (6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p); - } - continue; - } - } - - outputBits (6, l, c, lc, p); + int l = hufLength (hcode[im]); + + if (l == 0) + { + int zerun = 1; + + while ((im < iM) && (zerun < LONGEST_LONG_RUN)) + { + if (hufLength (hcode[im+1]) > 0 ) + break; + im++; + zerun++; + } + + if (zerun >= 2) + { + if (zerun >= SHORTEST_LONG_RUN) + { + outputBits (6, LONG_ZEROCODE_RUN, c, lc, p); + outputBits (8, zerun - SHORTEST_LONG_RUN, c, lc, p); + } + else + { + outputBits (6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p); + } + continue; + } + } + + outputBits (6, l, c, lc, p); } if (lc > 0) - *p++ = (unsigned char) (c << (8 - lc)); + *p++ = (unsigned char) (c << (8 - lc)); *pcode = p; } @@ -534,41 +537,41 @@ hufUnpackEncTable for (; im <= iM; im++) { - if (p - *pcode > ni) - unexpectedEndOfTable(); + if (p - *pcode > ni) + unexpectedEndOfTable(); - Int64 l = hcode[im] = getBits (6, c, lc, p); // code length + Int64 l = hcode[im] = getBits (6, c, lc, p); // code length - if (l == (Int64) LONG_ZEROCODE_RUN) - { - if (p - *pcode > ni) - unexpectedEndOfTable(); + if (l == (Int64) LONG_ZEROCODE_RUN) + { + if (p - *pcode > ni) + unexpectedEndOfTable(); - int zerun = getBits (8, c, lc, p) + SHORTEST_LONG_RUN; + int zerun = getBits (8, c, lc, p) + SHORTEST_LONG_RUN; - if (im + zerun > iM + 1) - tableTooLong(); + if (im + zerun > iM + 1) + tableTooLong(); - while (zerun--) - hcode[im++] = 0; + while (zerun--) + hcode[im++] = 0; - im--; - } - else if (l >= (Int64) SHORT_ZEROCODE_RUN) - { - int zerun = l - SHORT_ZEROCODE_RUN + 2; + im--; + } + else if (l >= (Int64) SHORT_ZEROCODE_RUN) + { + int zerun = l - SHORT_ZEROCODE_RUN + 2; - if (im + zerun > iM + 1) - tableTooLong(); + if (im + zerun > iM + 1) + tableTooLong(); - while (zerun--) - hcode[im++] = 0; + while (zerun--) + hcode[im++] = 0; - im--; - } + im--; + } } - *pcode = (char *) p; + *pcode = const_cast(p); hufCanonicalCodeTable (hcode); } @@ -585,7 +588,7 @@ hufUnpackEncTable void hufClearDecTable (HufDec * hdecod) // io: (allocated by caller) - // decoding table [HUF_DECSIZE] + // decoding table [HUF_DECSIZE] { memset (hdecod, 0, sizeof (HufDec) * HUF_DECSIZE); } @@ -605,7 +608,7 @@ hufBuildDecTable int im, // i : min index in hcode int iM, // i : max index in hcode HufDec * hdecod) // o: (allocated by caller) - // decoding table [HUF_DECSIZE] + // decoding table [HUF_DECSIZE] { // // Init hashtable & loop on all codes. @@ -614,81 +617,81 @@ hufBuildDecTable for (; im <= iM; im++) { - Int64 c = hufCode (hcode[im]); - int l = hufLength (hcode[im]); - - if (c >> l) - { - // - // Error: c is supposed to be an l-bit code, - // but c contains a value that is greater - // than the largest l-bit number. - // - - invalidTableEntry(); - } - - if (l > HUF_DECBITS) - { - // - // Long code: add a secondary entry - // - - HufDec *pl = hdecod + (c >> (l - HUF_DECBITS)); - - if (pl->len) - { - // - // Error: a short code has already - // been stored in table entry *pl. - // - - invalidTableEntry(); - } - - pl->lit++; - - if (pl->p) - { - int *p = pl->p; - pl->p = new int [pl->lit]; - - for (int i = 0; i < pl->lit - 1; ++i) - pl->p[i] = p[i]; - - delete [] p; - } - else - { - pl->p = new int [1]; - } - - pl->p[pl->lit - 1]= im; - } - else if (l) - { - // - // Short code: init all primary entries - // - - HufDec *pl = hdecod + (c << (HUF_DECBITS - l)); - - for (Int64 i = 1 << (HUF_DECBITS - l); i > 0; i--, pl++) - { - if (pl->len || pl->p) - { - // - // Error: a short code or a long code has - // already been stored in table entry *pl. - // - - invalidTableEntry(); - } - - pl->len = l; - pl->lit = im; - } - } + Int64 c = hufCode (hcode[im]); + int l = hufLength (hcode[im]); + + if (c >> l) + { + // + // Error: c is supposed to be an l-bit code, + // but c contains a value that is greater + // than the largest l-bit number. + // + + invalidTableEntry(); + } + + if (l > HUF_DECBITS) + { + // + // Long code: add a secondary entry + // + + HufDec *pl = hdecod + (c >> (l - HUF_DECBITS)); + + if (pl->len) + { + // + // Error: a short code has already + // been stored in table entry *pl. + // + + invalidTableEntry(); + } + + pl->lit++; + + if (pl->p) + { + int *p = pl->p; + pl->p = new int [pl->lit]; + + for (int i = 0; i < pl->lit - 1; ++i) + pl->p[i] = p[i]; + + delete [] p; + } + else + { + pl->p = new int [1]; + } + + pl->p[pl->lit - 1]= im; + } + else if (l) + { + // + // Short code: init all primary entries + // + + HufDec *pl = hdecod + (c << (HUF_DECBITS - l)); + + for (Int64 i = 1 << (HUF_DECBITS - l); i > 0; i--, pl++) + { + if (pl->len || pl->p) + { + // + // Error: a short code or a long code has + // already been stored in table entry *pl. + // + + invalidTableEntry(); + } + + pl->len = l; + pl->lit = im; + } + } } } @@ -702,11 +705,11 @@ hufFreeDecTable (HufDec *hdecod) // io: Decoding table { for (int i = 0; i < HUF_DECSIZE; i++) { - if (hdecod[i].p) - { - delete [] hdecod[i].p; - hdecod[i].p = 0; - } + if (hdecod[i].p) + { + delete [] hdecod[i].p; + hdecod[i].p = 0; + } } } @@ -724,20 +727,26 @@ outputCode (Int64 code, Int64 &c, int &lc, char *&out) inline void sendCode (Int64 sCode, int runCount, Int64 runCode, - Int64 &c, int &lc, char *&out) + Int64 &c, int &lc, char *&out) { - static const int RLMIN = 32; // min count to activate run-length coding - - if (runCount > RLMIN) + // + // Output a run of runCount instances of the symbol sCount. + // Output the symbols explicitly, or if that is shorter, output + // the sCode symbol once followed by a runCode symbol and runCount + // expressed as an 8-bit number. + // + + if (hufLength (sCode) + hufLength (runCode) + 8 < + hufLength (sCode) * runCount) { - outputCode (sCode, c, lc, out); - outputCode (runCode, c, lc, out); - outputBits (8, runCount, c, lc, out); + outputCode (sCode, c, lc, out); + outputCode (runCode, c, lc, out); + outputBits (8, runCount, c, lc, out); } else { - while (runCount-- >= 0) - outputCode (sCode, c, lc, out); + while (runCount-- >= 0) + outputCode (sCode, c, lc, out); } } @@ -766,21 +775,21 @@ hufEncode // return: output size (in bits) for (int i = 1; i < ni; i++) { - // - // Count same values or send code - // - - if (s == in[i] && cs < 255) - { - cs++; - } - else - { - sendCode (hcode[s], cs, hcode[rlc], c, lc, out); - cs=0; - } - - s = in[i]; + // + // Count same values or send code + // + + if (s == in[i] && cs < 255) + { + cs++; + } + else + { + sendCode (hcode[s], cs, hcode[rlc], c, lc, out); + cs=0; + } + + s = in[i]; } // @@ -790,7 +799,7 @@ hufEncode // return: output size (in bits) sendCode (hcode[s], cs, hcode[rlc], c, lc, out); if (lc) - *out = (c << (8 - lc)) & 0xff; + *out = (c << (8 - lc)) & 0xff; return (out - outStart) * 8 + lc; } @@ -813,32 +822,34 @@ hufEncode // return: output size (in bits) } -#define getCode(po, rlc, c, lc, in, out, oe) \ +#define getCode(po, rlc, c, lc, in, out, ob, oe)\ { \ if (po == rlc) \ { \ - if (lc < 8) \ - getChar(c, lc, in); \ - \ - lc -= 8; \ - \ - unsigned char cs = (c >> lc); \ - \ - if (out + cs > oe) \ - tooMuchData(); \ - \ - unsigned short s = out[-1]; \ - \ - while (cs-- > 0) \ - *out++ = s; \ + if (lc < 8) \ + getChar(c, lc, in); \ + \ + lc -= 8; \ + \ + unsigned char cs = (c >> lc); \ + \ + if (out + cs > oe) \ + tooMuchData(); \ + else if (out - 1 < ob) \ + notEnoughData(); \ + \ + unsigned short s = out[-1]; \ + \ + while (cs-- > 0) \ + *out++ = s; \ } \ else if (out < oe) \ { \ - *out++ = po; \ + *out++ = po; \ } \ else \ { \ - tooMuchData(); \ + tooMuchData(); \ } \ } @@ -869,63 +880,63 @@ hufDecode while (in < ie) { - getChar (c, lc, in); - - // - // Access decoding table - // - - while (lc >= HUF_DECBITS) - { - const HufDec pl = hdecod[(c >> (lc-HUF_DECBITS)) & HUF_DECMASK]; - - if (pl.len) - { - // - // Get short code - // - - lc -= pl.len; - getCode (pl.lit, rlc, c, lc, in, out, oe); - } - else - { - if (!pl.p) - invalidCode(); // wrong code - - // - // Search long code - // - - int j; - - for (j = 0; j < pl.lit; j++) - { - int l = hufLength (hcode[pl.p[j]]); - - while (lc < l && in < ie) // get more bits - getChar (c, lc, in); - - if (lc >= l) - { - if (hufCode (hcode[pl.p[j]]) == - ((c >> (lc - l)) & ((Int64(1) << l) - 1))) - { - // - // Found : get long code - // - - lc -= l; - getCode (pl.p[j], rlc, c, lc, in, out, oe); - break; - } - } - } - - if (j == pl.lit) - invalidCode(); // Not found - } - } + getChar (c, lc, in); + + // + // Access decoding table + // + + while (lc >= HUF_DECBITS) + { + const HufDec pl = hdecod[(c >> (lc-HUF_DECBITS)) & HUF_DECMASK]; + + if (pl.len) + { + // + // Get short code + // + + lc -= pl.len; + getCode (pl.lit, rlc, c, lc, in, out, outb, oe); + } + else + { + if (!pl.p) + invalidCode(); // wrong code + + // + // Search long code + // + + int j; + + for (j = 0; j < pl.lit; j++) + { + int l = hufLength (hcode[pl.p[j]]); + + while (lc < l && in < ie) // get more bits + getChar (c, lc, in); + + if (lc >= l) + { + if (hufCode (hcode[pl.p[j]]) == + ((c >> (lc - l)) & ((Int64(1) << l) - 1))) + { + // + // Found : get long code + // + + lc -= l; + getCode (pl.p[j], rlc, c, lc, in, out, outb, oe); + break; + } + } + } + + if (j == pl.lit) + invalidCode(); // Not found + } + } } // @@ -938,34 +949,34 @@ hufDecode while (lc > 0) { - const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK]; - - if (pl.len) - { - lc -= pl.len; - getCode (pl.lit, rlc, c, lc, in, out, oe); - } - else - { - invalidCode(); // wrong (long) code - } + const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK]; + + if (pl.len) + { + lc -= pl.len; + getCode (pl.lit, rlc, c, lc, in, out, outb, oe); + } + else + { + invalidCode(); // wrong (long) code + } } if (out - outb != no) - notEnoughData (); + notEnoughData (); } void countFrequencies (Int64 freq[HUF_ENCSIZE], - const unsigned short data[/*n*/], - int n) + const unsigned short data[/*n*/], + int n) { for (int i = 0; i < HUF_ENCSIZE; ++i) - freq[i] = 0; + freq[i] = 0; for (int i = 0; i < n; ++i) - ++freq[data[i]]; + ++freq[data[i]]; } @@ -987,9 +998,9 @@ readUInt (const char buf[4]) const unsigned char *b = (const unsigned char *) buf; return ( b[0] & 0x000000ff) | - ((b[1] << 8) & 0x0000ff00) | - ((b[2] << 16) & 0x00ff0000) | - ((b[3] << 24) & 0xff000000); + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + ((b[3] << 24) & 0xff000000); } } // namespace @@ -1002,17 +1013,18 @@ readUInt (const char buf[4]) int hufCompress (const unsigned short raw[], - int nRaw, - char compressed[]) + int nRaw, + char compressed[]) { if (nRaw == 0) - return 0; + return 0; AutoArray freq; countFrequencies (freq, raw, nRaw); - int im, iM; + int im = 0; + int iM = 0; hufBuildEncTable (freq, &im, &iM); char *tableStart = compressed + 20; @@ -1036,16 +1048,16 @@ hufCompress (const unsigned short raw[], void hufUncompress (const char compressed[], - int nCompressed, - unsigned short raw[], - int nRaw) + int nCompressed, + unsigned short raw[], + int nRaw) { if (nCompressed == 0) { - if (nRaw != 0) - notEnoughData(); + if (nRaw != 0) + notEnoughData(); - return; + return; } int im = readUInt (compressed); @@ -1054,33 +1066,51 @@ hufUncompress (const char compressed[], int nBits = readUInt (compressed + 12); if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE) - invalidTableSize(); + invalidTableSize(); const char *ptr = compressed + 20; - AutoArray freq; - AutoArray hdec; - - hufClearDecTable (hdec); - - hufUnpackEncTable (&ptr, nCompressed - (ptr - compressed), im, iM, freq); + // + // Fast decoder needs at least 2x64-bits of compressed data, and + // needs to be run-able on this platform. Otherwise, fall back + // to the original decoder + // - try + if (FastHufDecoder::enabled() && nBits > 128) { - if (nBits > 8 * (nCompressed - (ptr - compressed))) - invalidNBits(); - - hufBuildDecTable (freq, im, iM, hdec); - hufDecode (freq, hdec, ptr, nBits, iM, nRaw, raw); + FastHufDecoder fhd (ptr, nCompressed - (ptr - compressed), im, iM, iM); + fhd.decode ((unsigned char*)ptr, nBits, raw, nRaw); } - catch (...) + else { - hufFreeDecTable (hdec); - throw; - } + AutoArray freq; + AutoArray hdec; + + hufClearDecTable (hdec); - hufFreeDecTable (hdec); + hufUnpackEncTable (&ptr, + nCompressed - (ptr - compressed), + im, + iM, + freq); + + try + { + if (nBits > 8 * (nCompressed - (ptr - compressed))) + invalidNBits(); + + hufBuildDecTable (freq, im, iM, hdec); + hufDecode (freq, hdec, ptr, nBits, iM, nRaw, raw); + } + catch (...) + { + hufFreeDecTable (hdec); + throw; + } + + hufFreeDecTable (hdec); + } } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfHuf.h b/3rdparty/openexr/IlmImf/ImfHuf.h index 776d04bbb6..fa8960458b 100644 --- a/3rdparty/openexr/IlmImf/ImfHuf.h +++ b/3rdparty/openexr/IlmImf/ImfHuf.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -37,6 +37,8 @@ #ifndef INCLUDED_IMF_HUF_H #define INCLUDED_IMF_HUF_H +#include "ImfExport.h" +#include "ImfNamespace.h" //----------------------------------------------------------------------------- // @@ -58,22 +60,23 @@ // //----------------------------------------------------------------------------- -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER +IMF_EXPORT int hufCompress (const unsigned short raw[/*nRaw*/], - int nRaw, - char compressed[/*2 * nRaw + 65536*/]); - + int nRaw, + char compressed[/*2 * nRaw + 65536*/]); +IMF_EXPORT void hufUncompress (const char compressed[/*nCompressed*/], - int nCompressed, - unsigned short raw[/*nRaw*/], - int nRaw); + int nCompressed, + unsigned short raw[/*nRaw*/], + int nRaw); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfIO.cpp b/3rdparty/openexr/IlmImf/ImfIO.cpp index 0c651aa417..c52fc54587 100644 --- a/3rdparty/openexr/IlmImf/ImfIO.cpp +++ b/3rdparty/openexr/IlmImf/ImfIO.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,8 +41,9 @@ #include #include "Iex.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER IStream::IStream (const char fileName[]): _fileName (fileName) @@ -65,10 +66,10 @@ IStream::isMemoryMapped () const char * -IStream::readMemoryMapped (int) +IStream::readMemoryMapped (int n) { - throw Iex::InputExc ("Attempt to perform a memory-mapped read " - "on a file that is not memory mapped."); + throw IEX_NAMESPACE::InputExc ("Attempt to perform a memory-mapped read " + "on a file that is not memory mapped."); return 0; } @@ -106,4 +107,4 @@ OStream::fileName () const } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfIO.h b/3rdparty/openexr/IlmImf/ImfIO.h index 1e634fbceb..8c32fea917 100644 --- a/3rdparty/openexr/IlmImf/ImfIO.h +++ b/3rdparty/openexr/IlmImf/ImfIO.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,10 +42,14 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfInt64.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + #include -namespace Imf { + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER //----------------------------------------------------------- // class IStream -- an abstract base class for input streams. @@ -59,9 +63,10 @@ class IStream // Destructor //----------- + IMF_EXPORT virtual ~IStream (); - - + + //------------------------------------------------- // Does this input stream support memory-mapped IO? // @@ -71,6 +76,7 @@ class IStream // into a buffer supplied by the caller. //------------------------------------------------- + IMF_EXPORT virtual bool isMemoryMapped () const; @@ -85,8 +91,8 @@ class IStream //------------------------------------------------------ virtual bool read (char c[/*n*/], int n) = 0; - - + + //--------------------------------------------------- // Read from a memory-mapped stream: // @@ -95,9 +101,10 @@ class IStream // returned pointer remains valid until the stream // is closed. If there are less than n byte left to // read in the stream or if the stream is not memory- - // mapped, readMemoryMapped(n) throws an exception. + // mapped, readMemoryMapped(n) throws an exception. //--------------------------------------------------- + IMF_EXPORT virtual char * readMemoryMapped (int n); @@ -122,6 +129,7 @@ class IStream // Clear error conditions after an operation has failed. //------------------------------------------------------ + IMF_EXPORT virtual void clear (); @@ -129,10 +137,12 @@ class IStream // Get the name of the file associated with this stream. //------------------------------------------------------ + IMF_EXPORT const char * fileName () const; protected: + IMF_EXPORT IStream (const char fileName[]); private: @@ -156,8 +166,9 @@ class OStream // Destructor //----------- + IMF_EXPORT virtual ~OStream (); - + //---------------------------------------------------------- // Write to the stream: @@ -192,10 +203,12 @@ class OStream // Get the name of the file associated with this stream. //------------------------------------------------------ + IMF_EXPORT const char * fileName () const; protected: + IMF_EXPORT OStream (const char fileName[]); private: @@ -216,13 +229,13 @@ struct StreamIO static void writeChars (OStream &os, const char c[/*n*/], int n) { - os.write (c, n); + os.write (c, n); } static bool readChars (IStream &is, char c[/*n*/], int n) { - return is.read (c, n); + return is.read (c, n); } }; @@ -232,21 +245,20 @@ struct CharPtrIO static void writeChars (char *&op, const char c[/*n*/], int n) { - while (n--) - *op++ = *c++; + while (n--) + *op++ = *c++; } static bool readChars (const char *&ip, char c[/*n*/], int n) { - while (n--) - *c++ = *ip++; + while (n--) + *c++ = *ip++; - return true; + return true; } }; - -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfInputFile.cpp b/3rdparty/openexr/IlmImf/ImfInputFile.cpp index 5f031b2392..4aa885ee83 100644 --- a/3rdparty/openexr/IlmImf/ImfInputFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfInputFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -38,29 +38,38 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include +#include "ImfInputFile.h" +#include "ImfScanLineInputFile.h" +#include "ImfTiledInputFile.h" +#include "ImfChannelList.h" +#include "ImfMisc.h" +#include "ImfStdIO.h" +#include "ImfVersion.h" +#include "ImfPartType.h" +#include "ImfInputPartData.h" +#include "ImfMultiPartInputFile.h" + +#include +#include + #include "ImathFun.h" #include "IlmThreadMutex.h" #include "Iex.h" #include "half.h" + #include #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -using Imath::Box2i; -using Imath::divp; -using Imath::modp; -using IlmThread::Mutex; -using IlmThread::Lock; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::divp; +using IMATH_NAMESPACE::modp; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; // @@ -68,43 +77,60 @@ using IlmThread::Lock; // needed between calls to readPixels // -struct InputFile::Data: public Mutex +struct InputFile::Data : public Mutex { Header header; int version; - IStream * is; - bool deleteStream; + bool isTiled; TiledInputFile * tFile; ScanLineInputFile * sFile; + DeepScanLineInputFile * dsFile; LineOrder lineOrder; // the file's lineorder int minY; // data window's min y coord int maxY; // data window's max x coord - - FrameBuffer tFileBuffer; + + FrameBuffer tFileBuffer; FrameBuffer * cachedBuffer; - + CompositeDeepScanLine * compositor; // for loading deep files + int cachedTileY; int offset; - + int numThreads; - Data (bool del, int numThreads); + int partNumber; + InputPartData* part; + + bool multiPartBackwardSupport; + MultiPartInputFile* multiPartFile; + InputStreamMutex * _streamData; + bool _deleteStream; + + Data (int numThreads); ~Data (); void deleteCachedBuffer(); }; -InputFile::Data::Data (bool del, int numThreads): - is (0), - deleteStream (del), +InputFile::Data::Data (int numThreads): + isTiled (false), tFile (0), sFile (0), + dsFile(0), cachedBuffer (0), + compositor(0), cachedTileY (-1), - numThreads (numThreads) + numThreads (numThreads), + partNumber (-1), + part(NULL), + multiPartBackwardSupport (false), + multiPartFile (0), + _streamData(0), + _deleteStream(false) + { // empty } @@ -112,17 +138,23 @@ InputFile::Data::Data (bool del, int numThreads): InputFile::Data::~Data () { - delete tFile; - delete sFile; - - if (deleteStream) - delete is; + if (tFile) + delete tFile; + if (sFile) + delete sFile; + if (dsFile) + delete dsFile; + if (compositor) + delete compositor; deleteCachedBuffer(); + + if (multiPartBackwardSupport && multiPartFile) + delete multiPartFile; } -void +void InputFile::Data::deleteCachedBuffer() { // @@ -132,37 +164,39 @@ InputFile::Data::deleteCachedBuffer() if (cachedBuffer) { - for (FrameBuffer::Iterator k = cachedBuffer->begin(); - k != cachedBuffer->end(); - ++k) - { - Slice &s = k.slice(); + for (FrameBuffer::Iterator k = cachedBuffer->begin(); + k != cachedBuffer->end(); + ++k) + { + Slice &s = k.slice(); - switch (s.type) - { - case UINT: + switch (s.type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: - delete [] (((unsigned int *)s.base) + offset); - break; + delete [] (((unsigned int *)s.base) + offset); + break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: - delete [] ((half *)s.base + offset); - break; + delete [] ((half *)s.base + offset); + break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: - delete [] (((float *)s.base) + offset); - break; - } - } + delete [] (((float *)s.base) + offset); + break; + case NUM_PIXELTYPES : + throw(IEX_NAMESPACE::ArgExc("Invalid pixel type")); + } + } - // - // delete the cached frame buffer - // + // + // delete the cached frame buffer + // - delete cachedBuffer; - cachedBuffer = 0; + delete cachedBuffer; + cachedBuffer = 0; } } @@ -184,8 +218,8 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) if (minY < ifd->minY || maxY > ifd->maxY) { - throw Iex::ArgExc ("Tried to read scan line outside " - "the image file's data window."); + throw IEX_NAMESPACE::ArgExc ("Tried to read scan line outside " + "the image file's data window."); } // @@ -220,7 +254,7 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) // Box2i levelRange = ifd->tFile->dataWindowForLevel(0); - + // // Read the tiles into our temporary framebuffer and copy them into // the user's buffer @@ -259,24 +293,24 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) char *fromPtr, *toPtr; int size = pixelTypeSize (toSlice.type); - int xStart = levelRange.min.x; - int yStart = minYThisRow; + int xStart = levelRange.min.x; + int yStart = minYThisRow; - while (modp (xStart, toSlice.xSampling) != 0) - ++xStart; + while (modp (xStart, toSlice.xSampling) != 0) + ++xStart; - while (modp (yStart, toSlice.ySampling) != 0) - ++yStart; + while (modp (yStart, toSlice.ySampling) != 0) + ++yStart; for (int y = yStart; - y <= maxYThisRow; - y += toSlice.ySampling) + y <= maxYThisRow; + y += toSlice.ySampling) { - // + // // Set the pointers to the start of the y scanline in // this row of tiles - // - + // + fromPtr = fromSlice.base + (y - tileRange.min.y) * fromSlice.yStride + xStart * fromSlice.xStride; @@ -285,19 +319,19 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) divp (y, toSlice.ySampling) * toSlice.yStride + divp (xStart, toSlice.xSampling) * toSlice.xStride; - // + // // Copy all pixels for the scanline in this row of tiles - // + // for (int x = xStart; - x <= levelRange.max.x; - x += toSlice.xSampling) + x <= levelRange.max.x; + x += toSlice.xSampling) { - for (size_t i = 0; i < size; ++i) - toPtr[i] = fromPtr[i]; + for (int i = 0; i < size; ++i) + toPtr[i] = fromPtr[i]; - fromPtr += fromSlice.xStride * toSlice.xSampling; - toPtr += toSlice.xStride; + fromPtr += fromSlice.xStride * toSlice.xSampling; + toPtr += toSlice.xStride; } } } @@ -309,95 +343,278 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) InputFile::InputFile (const char fileName[], int numThreads): - _data (new Data (true, numThreads)) + _data (new Data (numThreads)) { + _data->_streamData = NULL; + _data->_deleteStream=true; + + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream* is = 0; try { - _data->is = new StdIFStream (fileName); - initialize(); + is = new StdIFStream (fileName); + readMagicNumberAndVersionField(*is, _data->version); + + // + // compatibility to read multipart file. + // + if (isMultiPart(_data->version)) + { + compatibilityInitialize(*is); + } + else + { + _data->_streamData = new InputStreamMutex(); + _data->_streamData->is = is; + _data->header.readFrom (*_data->_streamData->is, _data->version); + + // fix type attribute in single part regular image types + // (may be wrong if an old version of OpenEXR converts + // a tiled image to scanline or vice versa) + if(!isNonImage(_data->version) && + !isMultiPart(_data->version) && + _data->header.hasType()) + { + _data->header.setType(isTiled(_data->version) ? TILEDIMAGE : SCANLINEIMAGE); + } + + _data->header.sanityCheck (isTiled (_data->version)); + + initialize(); + } } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - delete _data; + if (is) delete is; + + if ( _data && !_data->multiPartBackwardSupport && _data->_streamData) + { + delete _data->_streamData; + _data->_streamData=NULL; + } + + if (_data) delete _data; + _data=NULL; REPLACE_EXC (e, "Cannot read image file " - "\"" << fileName << "\". " << e); + "\"" << fileName << "\". " << e.what()); throw; } catch (...) { - delete _data; + if (is) delete is; + if (_data && !_data->multiPartBackwardSupport && _data->_streamData) + { + delete _data->_streamData; + } + if (_data) delete _data; + throw; } } -InputFile::InputFile (IStream &is, int numThreads): - _data (new Data (false, numThreads)) +InputFile::InputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads): + _data (new Data (numThreads)) { + _data->_streamData=NULL; + _data->_deleteStream=false; try { - _data->is = &is; - initialize(); + readMagicNumberAndVersionField(is, _data->version); + + // + // Backward compatibility to read multpart file. + // + if (isMultiPart(_data->version)) + { + compatibilityInitialize(is); + } + else + { + _data->_streamData = new InputStreamMutex(); + _data->_streamData->is = &is; + _data->header.readFrom (*_data->_streamData->is, _data->version); + + // fix type attribute in single part regular image types + // (may be wrong if an old version of OpenEXR converts + // a tiled image to scanline or vice versa) + if(!isNonImage(_data->version) && + !isMultiPart(_data->version) && + _data->header.hasType()) + { + _data->header.setType(isTiled(_data->version) ? TILEDIMAGE : SCANLINEIMAGE); + } + + _data->header.sanityCheck (isTiled (_data->version)); + + initialize(); + } } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - delete _data; + if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + _data=NULL; REPLACE_EXC (e, "Cannot read image file " - "\"" << is.fileName() << "\". " << e); + "\"" << is.fileName() << "\". " << e.what()); throw; } catch (...) { - delete _data; + if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData; + if (_data) delete _data; + _data=NULL; throw; } } -void -InputFile::initialize () +InputFile::InputFile (InputPartData* part) : + _data (new Data (part->numThreads)) { - _data->header.readFrom (*_data->is, _data->version); - _data->header.sanityCheck (isTiled (_data->version)); + _data->_deleteStream=false; + multiPartInitialize (part); +} - if (isTiled (_data->version)) - { - _data->lineOrder = _data->header.lineOrder(); + +void +InputFile::compatibilityInitialize (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is) +{ + is.seekg(0); // - // Save the dataWindow information + // Construct a MultiPartInputFile, initialize InputFile + // with the part 0 data. + // (TODO) may want to have a way to set the reconstruction flag. // + _data->multiPartBackwardSupport = true; + _data->multiPartFile = new MultiPartInputFile(is, _data->numThreads); + InputPartData* part = _data->multiPartFile->getPart(0); + + multiPartInitialize (part); +} + + +void +InputFile::multiPartInitialize (InputPartData* part) +{ + _data->_streamData = part->mutex; + _data->version = part->version; + _data->header = part->header; + _data->partNumber = part->partNumber; + _data->part = part; + + initialize(); +} - const Box2i &dataWindow = _data->header.dataWindow(); - _data->minY = dataWindow.min.y; - _data->maxY = dataWindow.max.y; - _data->tFile = new TiledInputFile (_data->header, - _data->is, - _data->version, - _data->numThreads); +void +InputFile::initialize () +{ + if (!_data->part) + { + if(_data->header.hasType() && _data->header.type()==DEEPSCANLINE) + { + _data->isTiled=false; + const Box2i &dataWindow = _data->header.dataWindow(); + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; + + _data->dsFile = new DeepScanLineInputFile (_data->header, + _data->_streamData->is, + _data->version, + _data->numThreads); + _data->compositor = new CompositeDeepScanLine; + _data->compositor->addSource(_data->dsFile); + } + + else if (isTiled (_data->version)) + { + _data->isTiled = true; + _data->lineOrder = _data->header.lineOrder(); + + // + // Save the dataWindow information + // + + const Box2i &dataWindow = _data->header.dataWindow(); + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; + + _data->tFile = new TiledInputFile (_data->header, + _data->_streamData->is, + _data->version, + _data->numThreads); + } + + else if(!_data->header.hasType() || _data->header.type()==SCANLINEIMAGE) + { + _data->sFile = new ScanLineInputFile (_data->header, + _data->_streamData->is, + _data->numThreads); + }else{ + // type set but not recognised + + THROW(IEX_NAMESPACE::ArgExc, "InputFile cannot handle parts of type " << _data->header.type()); + } } else { - _data->sFile = new ScanLineInputFile (_data->header, - _data->is, - _data->numThreads); + if(_data->header.hasType() && _data->header.type()==DEEPSCANLINE) + { + _data->isTiled=false; + const Box2i &dataWindow = _data->header.dataWindow(); + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; + + _data->dsFile = new DeepScanLineInputFile (_data->part); + _data->compositor = new CompositeDeepScanLine; + _data->compositor->addSource(_data->dsFile); + } + else if (isTiled (_data->header.type())) + { + _data->isTiled = true; + _data->lineOrder = _data->header.lineOrder(); + + // + // Save the dataWindow information + // + + const Box2i &dataWindow = _data->header.dataWindow(); + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; + + _data->tFile = new TiledInputFile (_data->part); + } + else if(!_data->header.hasType() || _data->header.type()==SCANLINEIMAGE) + { + _data->sFile = new ScanLineInputFile (_data->part); + }else{ + THROW(IEX_NAMESPACE::ArgExc, "InputFile cannot handle parts of type " << _data->header.type()); + + } } } - +#include InputFile::~InputFile () { - delete _data; -} + if (_data->_deleteStream) + delete _data->_streamData->is; + // unless this file was opened via the multipart API, + // delete the streamData object too + if (_data->partNumber==-1 && _data->_streamData) + delete _data->_streamData; + + if (_data) delete _data; +} const char * InputFile::fileName () const { - return _data->is->fileName(); + return _data->_streamData->is->fileName(); } @@ -418,120 +635,123 @@ InputFile::version () const void InputFile::setFrameBuffer (const FrameBuffer &frameBuffer) { - if (isTiled (_data->version)) + if (_data->isTiled) { - Lock lock (*_data); + Lock lock (*_data); - // + // // We must invalidate the cached buffer if the new frame - // buffer has a different set of channels than the old - // frame buffer, or if the type of a channel has changed. - // + // buffer has a different set of channels than the old + // frame buffer, or if the type of a channel has changed. + // - const FrameBuffer &oldFrameBuffer = _data->tFileBuffer; + const FrameBuffer &oldFrameBuffer = _data->tFileBuffer; - FrameBuffer::ConstIterator i = oldFrameBuffer.begin(); - FrameBuffer::ConstIterator j = frameBuffer.begin(); + FrameBuffer::ConstIterator i = oldFrameBuffer.begin(); + FrameBuffer::ConstIterator j = frameBuffer.begin(); - while (i != oldFrameBuffer.end() && j != frameBuffer.end()) - { - if (strcmp (i.name(), j.name()) || i.slice().type != j.slice().type) - break; + while (i != oldFrameBuffer.end() && j != frameBuffer.end()) + { + if (strcmp (i.name(), j.name()) || i.slice().type != j.slice().type) + break; - ++i; - ++j; - } + ++i; + ++j; + } - if (i != oldFrameBuffer.end() || j != frameBuffer.end()) + if (i != oldFrameBuffer.end() || j != frameBuffer.end()) { - // - // Invalidate the cached buffer. - // + // + // Invalidate the cached buffer. + // _data->deleteCachedBuffer (); - _data->cachedTileY = -1; - - // - // Create new a cached frame buffer. It can hold a single - // row of tiles. The cached buffer can be reused for each - // row of tiles because we set the yTileCoords parameter of - // each Slice to true. - // - - const Box2i &dataWindow = _data->header.dataWindow(); - _data->cachedBuffer = new FrameBuffer(); - _data->offset = dataWindow.min.x; - - int tileRowSize = (dataWindow.max.x - dataWindow.min.x + 1) * - _data->tFile->tileYSize(); - - for (FrameBuffer::ConstIterator k = frameBuffer.begin(); - k != frameBuffer.end(); - ++k) - { - Slice s = k.slice(); - - switch (s.type) - { - case UINT: - - _data->cachedBuffer->insert - (k.name(), - Slice (UINT, - (char *)(new unsigned int[tileRowSize] - - _data->offset), - sizeof (unsigned int), - sizeof (unsigned int) * - _data->tFile->levelWidth(0), - 1, 1, - s.fillValue, - false, true)); - break; - - case HALF: - - _data->cachedBuffer->insert - (k.name(), - Slice (HALF, - (char *)(new half[tileRowSize] - - _data->offset), - sizeof (half), - sizeof (half) * - _data->tFile->levelWidth(0), - 1, 1, - s.fillValue, - false, true)); - break; - - case FLOAT: - - _data->cachedBuffer->insert - (k.name(), - Slice (FLOAT, - (char *)(new float[tileRowSize] - - _data->offset), - sizeof(float), - sizeof(float) * - _data->tFile->levelWidth(0), - 1, 1, - s.fillValue, - false, true)); - break; - - default: - - throw Iex::ArgExc ("Unknown pixel data type."); - } - } - - _data->tFile->setFrameBuffer (*_data->cachedBuffer); + _data->cachedTileY = -1; + + // + // Create new a cached frame buffer. It can hold a single + // row of tiles. The cached buffer can be reused for each + // row of tiles because we set the yTileCoords parameter of + // each Slice to true. + // + + const Box2i &dataWindow = _data->header.dataWindow(); + _data->cachedBuffer = new FrameBuffer(); + _data->offset = dataWindow.min.x; + + int tileRowSize = (dataWindow.max.x - dataWindow.min.x + 1) * + _data->tFile->tileYSize(); + + for (FrameBuffer::ConstIterator k = frameBuffer.begin(); + k != frameBuffer.end(); + ++k) + { + Slice s = k.slice(); + + switch (s.type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + _data->cachedBuffer->insert + (k.name(), + Slice (UINT, + (char *)(new unsigned int[tileRowSize] - + _data->offset), + sizeof (unsigned int), + sizeof (unsigned int) * + _data->tFile->levelWidth(0), + 1, 1, + s.fillValue, + false, true)); + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + _data->cachedBuffer->insert + (k.name(), + Slice (HALF, + (char *)(new half[tileRowSize] - + _data->offset), + sizeof (half), + sizeof (half) * + _data->tFile->levelWidth(0), + 1, 1, + s.fillValue, + false, true)); + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + _data->cachedBuffer->insert + (k.name(), + Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT, + (char *)(new float[tileRowSize] - + _data->offset), + sizeof(float), + sizeof(float) * + _data->tFile->levelWidth(0), + 1, 1, + s.fillValue, + false, true)); + break; + + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + } + + _data->tFile->setFrameBuffer (*_data->cachedBuffer); } - _data->tFileBuffer = frameBuffer; + _data->tFileBuffer = frameBuffer; } - else + else if(_data->compositor) { - _data->sFile->setFrameBuffer (frameBuffer); + _data->compositor->setFrameBuffer(frameBuffer); + }else { + _data->sFile->setFrameBuffer(frameBuffer); + _data->tFileBuffer = frameBuffer; } } @@ -539,14 +759,18 @@ InputFile::setFrameBuffer (const FrameBuffer &frameBuffer) const FrameBuffer & InputFile::frameBuffer () const { - if (isTiled (_data->version)) + if(_data->compositor) + { + return _data->compositor->frameBuffer(); + } + else if(_data->isTiled) { - Lock lock (*_data); - return _data->tFileBuffer; + Lock lock (*_data); + return _data->tFileBuffer; } else { - return _data->sFile->frameBuffer(); + return _data->sFile->frameBuffer(); } } @@ -554,19 +778,36 @@ InputFile::frameBuffer () const bool InputFile::isComplete () const { - if (isTiled (_data->version)) - return _data->tFile->isComplete(); + if (_data->dsFile) + return _data->dsFile->isComplete(); + else if (_data->isTiled) + return _data->tFile->isComplete(); else - return _data->sFile->isComplete(); + return _data->sFile->isComplete(); +} + +bool +InputFile::isOptimizationEnabled() const +{ + if(_data->sFile) + { + return _data->sFile->isOptimizationEnabled(); + }else{ + return false; + } } void InputFile::readPixels (int scanLine1, int scanLine2) { - if (isTiled (_data->version)) + if (_data->compositor) + { + _data->compositor->readPixels(scanLine1,scanLine2); + } + else if (_data->isTiled) { - Lock lock (*_data); + Lock lock (*_data); bufferedReadPixels (_data, scanLine1, scanLine2); } else @@ -585,49 +826,88 @@ InputFile::readPixels (int scanLine) void InputFile::rawPixelData (int firstScanLine, - const char *&pixelData, - int &pixelDataSize) + const char *&pixelData, + int &pixelDataSize) { try { - if (isTiled (_data->version)) - { - throw Iex::ArgExc ("Tried to read a raw scanline " - "from a tiled image."); - } - + if (_data->dsFile) + { + throw IEX_NAMESPACE::ArgExc ("Tried to read a raw scanline " + "from a deep image."); + } + + else if (_data->isTiled) + { + throw IEX_NAMESPACE::ArgExc ("Tried to read a raw scanline " + "from a tiled image."); + } + _data->sFile->rawPixelData (firstScanLine, pixelData, pixelDataSize); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error reading pixel data from image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error reading pixel data from image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } + + void -InputFile::rawTileData (int &dx, int &dy, - int &lx, int &ly, - const char *&pixelData, - int &pixelDataSize) +InputFile::rawPixelDataToBuffer (int scanLine, + char *pixelData, + int &pixelDataSize) const { try { - if (!isTiled (_data->version)) + if (_data->dsFile) + { + throw IEX_NAMESPACE::ArgExc ("Tried to read a raw scanline " + "from a deep image."); + } + + else if (_data->isTiled) + { + throw IEX_NAMESPACE::ArgExc ("Tried to read a raw scanline " + "from a tiled image."); + } + + _data->sFile->rawPixelDataToBuffer(scanLine, pixelData, pixelDataSize); + } + catch (IEX_NAMESPACE::BaseExc &e) { - throw Iex::ArgExc ("Tried to read a raw tile " - "from a scanline-based image."); + REPLACE_EXC (e, "Error reading pixel data from image " + "file \"" << fileName() << "\". " << e.what()); + throw; } +} + + +void +InputFile::rawTileData (int &dx, int &dy, + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize) +{ + try + { + if (!_data->isTiled) + { + throw IEX_NAMESPACE::ArgExc ("Tried to read a raw tile " + "from a scanline-based image."); + } + _data->tFile->rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error reading tile data from image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error reading tile data from image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -635,14 +915,14 @@ InputFile::rawTileData (int &dx, int &dy, TiledInputFile* InputFile::tFile() { - if (!isTiled (_data->version)) + if (!_data->isTiled) { - throw Iex::ArgExc ("Cannot get a TiledInputFile pointer " - "from an InputFile that is not tiled."); + throw IEX_NAMESPACE::ArgExc ("Cannot get a TiledInputFile pointer " + "from an InputFile that is not tiled."); } return _data->tFile; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfInputFile.h b/3rdparty/openexr/IlmImf/ImfInputFile.h index 76d5b60147..cc524a25cf 100644 --- a/3rdparty/openexr/IlmImf/ImfInputFile.h +++ b/3rdparty/openexr/IlmImf/ImfInputFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,20 +43,22 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfTiledOutputFile.h" +#include "ImfThreading.h" +#include "ImfGenericInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + #include -#include -namespace Imf { -class TiledInputFile; -class ScanLineInputFile; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -class InputFile +class InputFile : public GenericInputFile { public: @@ -68,6 +70,7 @@ class InputFile // used to read the file (see ImfThreading.h). //----------------------------------------------------------- + IMF_EXPORT InputFile (const char fileName[], int numThreads = globalThreadCount()); @@ -80,13 +83,15 @@ class InputFile // used to read the file (see ImfThreading.h). //------------------------------------------------------------- - InputFile (IStream &is, int numThreads = globalThreadCount()); + IMF_EXPORT + InputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount()); //----------- // Destructor //----------- + IMF_EXPORT virtual ~InputFile (); @@ -94,6 +99,7 @@ class InputFile // Access to the file name //------------------------ + IMF_EXPORT const char * fileName () const; @@ -101,6 +107,7 @@ class InputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; @@ -108,6 +115,7 @@ class InputFile // Access to the file format version //---------------------------------- + IMF_EXPORT int version () const; @@ -122,6 +130,7 @@ class InputFile // to readPixels(). //----------------------------------------------------------- + IMF_EXPORT void setFrameBuffer (const FrameBuffer &frameBuffer); @@ -129,6 +138,7 @@ class InputFile // Access to the current frame buffer //----------------------------------- + IMF_EXPORT const FrameBuffer & frameBuffer () const; @@ -141,8 +151,33 @@ class InputFile // writing may have been aborted prematurely.) //--------------------------------------------------------------- + IMF_EXPORT bool isComplete () const; + + //--------------------------------------------------------------- + // Check if SSE optimization is enabled + // + // Call after setFrameBuffer() to query whether optimized file decoding + // is available - decode times will be faster if returns true + // + // Optimization depends on: + // the file type (only scanline data is supported), + // the framebuffer channels (RGB/RGBA mono or stereo) + // the framebuffer channel types (all channels half-float format only) + // the file channels (RGB/RGBA mono or stereo) + // the file channel types (all channel half-float format only) + // whether SSE2 instruction support was detected at compile time + // + // Calling isOptimizationEnabled before setFrameBuffer will throw an exception + // + //--------------------------------------------------------------- + + IMF_EXPORT + bool isOptimizationEnabled () const; + + + //--------------------------------------------------------------- // Read pixel data: @@ -163,7 +198,9 @@ class InputFile // //--------------------------------------------------------------- + IMF_EXPORT void readPixels (int scanLine1, int scanLine2); + IMF_EXPORT void readPixels (int scanLine); @@ -173,9 +210,34 @@ class InputFile // used to implement OutputFile::copyPixels()). //---------------------------------------------- + IMF_EXPORT void rawPixelData (int firstScanLine, - const char *&pixelData, - int &pixelDataSize); + const char *&pixelData, + int &pixelDataSize); + + + //---------------------------------------------- + // Read a scanline's worth of raw pixel data + // from the file, without uncompressing it, and + // store in an external buffer, pixelData. + // pixelData should be pre-allocated with space + // for pixelDataSize chars. + // + // This function can be used to separate the + // reading of a raw scan line from the + // decompression of that scan line, for + // example to allow multiple scan lines to be + // decompressed in parallel by an application's + // own threads, where it is not convenient to + // use the threading within the library. + //---------------------------------------------- + + IMF_EXPORT + void rawPixelDataToBuffer (int scanLine, + char *pixelData, + int &pixelDataSize) const; + + //-------------------------------------------------- // Read a tile of raw pixel data from the file, @@ -183,27 +245,34 @@ class InputFile // used to implement TiledOutputFile::copyPixels()). //-------------------------------------------------- + IMF_EXPORT void rawTileData (int &dx, int &dy, - int &lx, int &ly, - const char *&pixelData, - int &pixelDataSize); + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize); struct Data; - + private: + InputFile (InputPartData* part); InputFile (const InputFile &); // not implemented InputFile & operator = (const InputFile &); // not implemented void initialize (); + void multiPartInitialize(InputPartData* part); + void compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is); TiledInputFile * tFile (); - + friend void TiledOutputFile::copyPixels (InputFile &); - + Data * _data; + + + friend class MultiPartInputFile; }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfInputPart.cpp b/3rdparty/openexr/IlmImf/ImfInputPart.cpp new file mode 100644 index 0000000000..d548592d85 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfInputPart.cpp @@ -0,0 +1,122 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfInputPart.h" +#include "ImfNamespace.h" + +#include "ImfMultiPartInputFile.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +InputPart::InputPart(MultiPartInputFile& multiPartFile, int partNumber) +{ + file = multiPartFile.getInputPart(partNumber); +} + +const char * +InputPart::fileName () const +{ + return file->fileName(); +} + +const Header & +InputPart::header () const +{ + return file->header(); +} + +int +InputPart::version () const +{ + return file->version(); +} + +void +InputPart::setFrameBuffer (const FrameBuffer &frameBuffer) +{ + file->setFrameBuffer(frameBuffer); +} + +const FrameBuffer & +InputPart::frameBuffer () const +{ + return file->frameBuffer(); +} + +bool +InputPart::isComplete () const +{ + return file->isComplete(); +} + +bool +InputPart::isOptimizationEnabled() const +{ + return file->isOptimizationEnabled(); +} + +void +InputPart::readPixels (int scanLine1, int scanLine2) +{ + file->readPixels(scanLine1, scanLine2); +} + +void +InputPart::readPixels (int scanLine) +{ + file->readPixels(scanLine); +} + +void +InputPart::rawPixelData (int firstScanLine, const char *&pixelData, int &pixelDataSize) +{ + file->rawPixelData(firstScanLine, pixelData, pixelDataSize); +} + + +void +InputPart::rawPixelDataToBuffer (int scanLine, char *pixelData, int &pixelDataSize) const +{ + file->rawPixelDataToBuffer(scanLine, pixelData, pixelDataSize); +} + + +void +InputPart::rawTileData (int &dx, int &dy, int &lx, int &ly, + const char *&pixelData, int &pixelDataSize) +{ + file->rawTileData(dx, dy, lx, ly, pixelData, pixelDataSize); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfInputPart.h b/3rdparty/openexr/IlmImf/ImfInputPart.h new file mode 100644 index 0000000000..1afb86e07e --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfInputPart.h @@ -0,0 +1,104 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFINPUTPART_H_ +#define IMFINPUTPART_H_ + +#include "ImfInputFile.h" +#include "ImfOutputPart.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//------------------------------------------------------------------- +// class InputPart: +// +// Same interface as InputFile. Please refer to InputFile. +//------------------------------------------------------------------- + +class InputPart +{ + public: + IMF_EXPORT + InputPart(MultiPartInputFile& multiPartFile, int partNumber); + + IMF_EXPORT + const char * fileName () const; + IMF_EXPORT + const Header & header () const; + IMF_EXPORT + int version () const; + IMF_EXPORT + void setFrameBuffer (const FrameBuffer &frameBuffer); + IMF_EXPORT + const FrameBuffer & frameBuffer () const; + IMF_EXPORT + bool isComplete () const; + IMF_EXPORT + bool isOptimizationEnabled () const; + IMF_EXPORT + void readPixels (int scanLine1, int scanLine2); + IMF_EXPORT + void readPixels (int scanLine); + IMF_EXPORT + void rawPixelData (int firstScanLine, + const char *&pixelData, + int &pixelDataSize); + + + IMF_EXPORT + void rawPixelDataToBuffer (int scanLine, + char *pixelData, + int &pixelDataSize) const; + + + IMF_EXPORT + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize); + + private: + InputFile* file; + // for internal use - give OutputFile and TiledOutputFile access to file for copyPixels + friend void OutputFile::copyPixels(InputPart&); + friend void TiledOutputFile::copyPixels(InputPart&); + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFINPUTPART_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfInputPartData.cpp b/3rdparty/openexr/IlmImf/ImfInputPartData.cpp new file mode 100644 index 0000000000..d241aed9cc --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfInputPartData.cpp @@ -0,0 +1,51 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfInputPartData.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +InputPartData::InputPartData(InputStreamMutex* mutex, const Header &header, + int partNumber, int numThreads, int version): + header(header), + numThreads(numThreads), + partNumber(partNumber), + version(version), + mutex(mutex), + completed(false) +{ +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfInputPartData.h b/3rdparty/openexr/IlmImf/ImfInputPartData.h new file mode 100644 index 0000000000..fb9f86ec29 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfInputPartData.h @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFINPUTPARTDATA_H_ +#define IMFINPUTPARTDATA_H_ + +#include + +#include "ImfInputStreamMutex.h" +#include "ImfHeader.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +struct InputPartData +{ + Header header; + int numThreads; + int partNumber; + int version; + InputStreamMutex* mutex; + std::vector chunkOffsets; + bool completed; + + IMF_EXPORT + InputPartData(InputStreamMutex* mutex, const Header &header, + int partNumber, int numThreads, int version); + +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif /* IMFINPUTPARTDATA_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfInputStreamMutex.h b/3rdparty/openexr/IlmImf/ImfInputStreamMutex.h new file mode 100644 index 0000000000..c491dbee1e --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfInputStreamMutex.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFINPUTSTREAMMUTEX_H_ +#define IMFINPUTSTREAMMUTEX_H_ + +#include "ImfIO.h" +#include "IlmThreadMutex.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +using ILMTHREAD_NAMESPACE::Mutex; + +// +// Used to wrap OPENEXR_IMF_INTERNAL_NAMESPACE::IStream as a Mutex. +// +struct InputStreamMutex : public Mutex +{ + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream* is; + Int64 currentPosition; + + InputStreamMutex() + { + is = 0; + currentPosition = 0; + } +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif /* IMFINPUTSTREAMMUTEX_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfInt64.h b/3rdparty/openexr/IlmImf/ImfInt64.h index 065df922ab..eca020c055 100644 --- a/3rdparty/openexr/IlmImf/ImfInt64.h +++ b/3rdparty/openexr/IlmImf/ImfInt64.h @@ -2,9 +2,9 @@ // // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,11 +42,16 @@ //---------------------------------------------------------------------------- #include "ImathInt64.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +using IMATH_NAMESPACE::Int64; +using IMATH_NAMESPACE::SInt64; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -namespace Imf { -using Imath::Int64; -} // namespace Imf -#endif +#endif // INCLUDED_IMF_INT64_H diff --git a/3rdparty/openexr/IlmImf/ImfIntAttribute.cpp b/3rdparty/openexr/IlmImf/ImfIntAttribute.cpp index 6537b4a6a7..7486a2ed83 100644 --- a/3rdparty/openexr/IlmImf/ImfIntAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfIntAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,7 +43,7 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER template <> @@ -54,4 +54,4 @@ IntAttribute::staticTypeName () } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfIntAttribute.h b/3rdparty/openexr/IlmImf/ImfIntAttribute.h index 2f29ad64a9..3d271cabe4 100644 --- a/3rdparty/openexr/IlmImf/ImfIntAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfIntAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,21 +43,16 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfAttribute.h" +#include "ImfNamespace.h" - -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER typedef TypedAttribute IntAttribute; -template <> const char *IntAttribute::staticTypeName (); - +template <> IMF_EXPORT const char *IntAttribute::staticTypeName (); -} // namespace Imf -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfKeyCode.cpp b/3rdparty/openexr/IlmImf/ImfKeyCode.cpp index f2f726fdb7..f90e4334e6 100644 --- a/3rdparty/openexr/IlmImf/ImfKeyCode.cpp +++ b/3rdparty/openexr/IlmImf/ImfKeyCode.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,17 +41,18 @@ #include #include "Iex.h" +#include "ImfNamespace.h" -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + KeyCode::KeyCode (int filmMfcCode, - int filmType, - int prefix, - int count, - int perfOffset, - int perfsPerFrame, - int perfsPerCount) + int filmType, + int prefix, + int count, + int perfOffset, + int perfsPerFrame, + int perfsPerCount) { setFilmMfcCode (filmMfcCode); setFilmType (filmType); @@ -90,95 +91,95 @@ KeyCode::operator = (const KeyCode &other) } -int +int KeyCode::filmMfcCode () const { return _filmMfcCode; } -void +void KeyCode::setFilmMfcCode (int filmMfcCode) { if (filmMfcCode < 0 || filmMfcCode > 99) - throw Iex::ArgExc ("Invalid key code film manufacturer code " - "(must be between 0 and 99)."); + throw IEX_NAMESPACE::ArgExc ("Invalid key code film manufacturer code " + "(must be between 0 and 99)."); _filmMfcCode = filmMfcCode; } -int +int KeyCode::filmType () const { return _filmType; } -void +void KeyCode::setFilmType (int filmType) { if (filmType < 0 || filmType > 99) - throw Iex::ArgExc ("Invalid key code film type " - "(must be between 0 and 99)."); + throw IEX_NAMESPACE::ArgExc ("Invalid key code film type " + "(must be between 0 and 99)."); _filmType = filmType; } -int +int KeyCode::prefix () const { return _prefix; } -void +void KeyCode::setPrefix (int prefix) { if (prefix < 0 || prefix > 999999) - throw Iex::ArgExc ("Invalid key code prefix " - "(must be between 0 and 999999)."); + throw IEX_NAMESPACE::ArgExc ("Invalid key code prefix " + "(must be between 0 and 999999)."); _prefix = prefix; } -int +int KeyCode::count () const { return _count; } -void +void KeyCode::setCount (int count) { if (count < 0 || count > 9999) - throw Iex::ArgExc ("Invalid key code count " - "(must be between 0 and 9999)."); + throw IEX_NAMESPACE::ArgExc ("Invalid key code count " + "(must be between 0 and 9999)."); _count = count; } -int +int KeyCode::perfOffset () const { return _perfOffset; } -void +void KeyCode::setPerfOffset (int perfOffset) { if (perfOffset < 0 || perfOffset > 119) - throw Iex::ArgExc ("Invalid key code perforation offset " - "(must be between 0 and 119)."); + throw IEX_NAMESPACE::ArgExc ("Invalid key code perforation offset " + "(must be between 0 and 119)."); _perfOffset = perfOffset; } -int +int KeyCode::perfsPerFrame () const { return _perfsPerFrame; @@ -189,14 +190,14 @@ void KeyCode::setPerfsPerFrame (int perfsPerFrame) { if (perfsPerFrame < 1 || perfsPerFrame > 15) - throw Iex::ArgExc ("Invalid key code number of perforations per frame " - "(must be between 1 and 15)."); + throw IEX_NAMESPACE::ArgExc ("Invalid key code number of perforations per frame " + "(must be between 1 and 15)."); _perfsPerFrame = perfsPerFrame; } -int +int KeyCode::perfsPerCount () const { return _perfsPerCount; @@ -207,10 +208,10 @@ void KeyCode::setPerfsPerCount (int perfsPerCount) { if (perfsPerCount < 20 || perfsPerCount > 120) - throw Iex::ArgExc ("Invalid key code number of perforations per count " - "(must be between 20 and 120)."); + throw IEX_NAMESPACE::ArgExc ("Invalid key code number of perforations per count " + "(must be between 20 and 120)."); _perfsPerCount = perfsPerCount; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfKeyCode.h b/3rdparty/openexr/IlmImf/ImfKeyCode.h index c619b1c15c..37f0ddd0d4 100644 --- a/3rdparty/openexr/IlmImf/ImfKeyCode.h +++ b/3rdparty/openexr/IlmImf/ImfKeyCode.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,7 +39,7 @@ //----------------------------------------------------------------------------- // // class KeyCode -// +// // A KeyCode object uniquely identifies a motion picture film frame. // The following fields specifiy film manufacturer, film type, film // roll and the frame's position within the roll: @@ -61,7 +61,7 @@ // zero-frame reference mark // range: 0 - 119 // -// perfsPerFrame number of perforations per frame +// perfsPerFrame number of perforations per frame // range: 1 - 15 // // typical values: @@ -70,7 +70,7 @@ // 3, 4, or 8 for 35mm film // 5, 8 or 15 for 65mm film // -// perfsPerCount number of perforations per count +// perfsPerCount number of perforations per count // range: 20 - 120 // // typical values: @@ -95,10 +95,12 @@ // Latent Image Identification Information // //----------------------------------------------------------------------------- +#include "ImfNamespace.h" +#include "ImfExport.h" -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + class KeyCode { public: @@ -107,15 +109,18 @@ class KeyCode // Constructors and assignment operator //------------------------------------- + IMF_EXPORT KeyCode (int filmMfcCode = 0, - int filmType = 0, - int prefix = 0, - int count = 0, - int perfOffset = 0, - int perfsPerFrame = 4, - int perfsPerCount = 64); - + int filmType = 0, + int prefix = 0, + int count = 0, + int perfOffset = 0, + int perfsPerFrame = 4, + int perfsPerCount = 64); + + IMF_EXPORT KeyCode (const KeyCode &other); + IMF_EXPORT KeyCode & operator = (const KeyCode &other); @@ -123,25 +128,39 @@ class KeyCode // Access to individual fields //---------------------------- + IMF_EXPORT int filmMfcCode () const; + IMF_EXPORT void setFilmMfcCode (int filmMfcCode); + IMF_EXPORT int filmType () const; + IMF_EXPORT void setFilmType (int filmType); + IMF_EXPORT int prefix () const; + IMF_EXPORT void setPrefix (int prefix); + IMF_EXPORT int count () const; + IMF_EXPORT void setCount (int count); + IMF_EXPORT int perfOffset () const; + IMF_EXPORT void setPerfOffset (int perfOffset); + IMF_EXPORT int perfsPerFrame () const; + IMF_EXPORT void setPerfsPerFrame (int perfsPerFrame); + IMF_EXPORT int perfsPerCount () const; + IMF_EXPORT void setPerfsPerCount (int perfsPerCount); private: @@ -156,6 +175,10 @@ class KeyCode }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfKeyCodeAttribute.cpp b/3rdparty/openexr/IlmImf/ImfKeyCodeAttribute.cpp index 6880274cef..06c666bb37 100644 --- a/3rdparty/openexr/IlmImf/ImfKeyCodeAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfKeyCodeAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,8 +41,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -54,7 +55,7 @@ KeyCodeAttribute::staticTypeName () template <> void -KeyCodeAttribute::writeValueTo (OStream &os, int) const +KeyCodeAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.filmMfcCode()); Xdr::write (os, _value.filmType()); @@ -68,7 +69,7 @@ KeyCodeAttribute::writeValueTo (OStream &os, int) const template <> void -KeyCodeAttribute::readValueFrom (IStream &is, int, int) +KeyCodeAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { int tmp; @@ -95,4 +96,4 @@ KeyCodeAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfKeyCodeAttribute.h b/3rdparty/openexr/IlmImf/ImfKeyCodeAttribute.h index 551d7d3b3a..00d4ece9f5 100644 --- a/3rdparty/openexr/IlmImf/ImfKeyCodeAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfKeyCodeAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,30 +43,31 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfKeyCode.h" +#include "ImfExport.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -typedef TypedAttribute KeyCodeAttribute; +typedef TypedAttribute KeyCodeAttribute; template <> +IMF_EXPORT const char *KeyCodeAttribute::staticTypeName (); template <> -void KeyCodeAttribute::writeValueTo (OStream &, int) const; +IMF_EXPORT +void KeyCodeAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; template <> -void KeyCodeAttribute::readValueFrom (IStream &, int, int); +IMF_EXPORT +void KeyCodeAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); -} // namespace Imf - -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfLineOrder.h b/3rdparty/openexr/IlmImf/ImfLineOrder.h index fd3d2238d7..8f30bed1fc 100644 --- a/3rdparty/openexr/IlmImf/ImfLineOrder.h +++ b/3rdparty/openexr/IlmImf/ImfLineOrder.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,8 +42,9 @@ // enum LineOrder // //----------------------------------------------------------------------------- +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER enum LineOrder @@ -53,12 +54,16 @@ enum LineOrder DECREASING_Y = 1, // first scan line has highest y coordinate RANDOM_Y = 2, // only for tiled files; tiles are written - // in random order + // in random order NUM_LINEORDERS // number of different line orders }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfLineOrderAttribute.cpp b/3rdparty/openexr/IlmImf/ImfLineOrderAttribute.cpp index 9ce58c22cc..aebbac7e77 100644 --- a/3rdparty/openexr/IlmImf/ImfLineOrderAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfLineOrderAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,11 +41,12 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfLineOrderAttribute.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -57,7 +58,7 @@ LineOrderAttribute::staticTypeName () template <> void -LineOrderAttribute::writeValueTo (OStream &os, int) const +LineOrderAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { unsigned char tmp = _value; Xdr::write (os, tmp); @@ -66,7 +67,7 @@ LineOrderAttribute::writeValueTo (OStream &os, int) const template <> void -LineOrderAttribute::readValueFrom (IStream &is, int, int) +LineOrderAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { unsigned char tmp; Xdr::read (is, tmp); @@ -74,4 +75,4 @@ LineOrderAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfLineOrderAttribute.h b/3rdparty/openexr/IlmImf/ImfLineOrderAttribute.h index fd84b15f98..342c3d0563 100644 --- a/3rdparty/openexr/IlmImf/ImfLineOrderAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfLineOrderAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,24 +43,30 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfLineOrder.h" +#include "ImfExport.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { +typedef TypedAttribute LineOrderAttribute; -typedef TypedAttribute LineOrderAttribute; -template <> const char *LineOrderAttribute::staticTypeName (); -template <> void LineOrderAttribute::writeValueTo (OStream &, int) const; -template <> void LineOrderAttribute::readValueFrom (IStream &, int, int); +template <> +IMF_EXPORT +const char *LineOrderAttribute::staticTypeName (); +template <> +IMF_EXPORT +void LineOrderAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; -} // namespace Imf +template <> +IMF_EXPORT +void LineOrderAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfLut.cpp b/3rdparty/openexr/IlmImf/ImfLut.cpp index 4c4ce8c4b8..3209abc40f 100644 --- a/3rdparty/openexr/IlmImf/ImfLut.cpp +++ b/3rdparty/openexr/IlmImf/ImfLut.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,8 +45,9 @@ #include #include #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER void @@ -54,15 +55,15 @@ HalfLut::apply (half *data, int nData, int stride) const { while (nData) { - *data = _lut (*data); - data += stride; - nData -= 1; + *data = _lut (*data); + data += stride; + nData -= 1; } } void -HalfLut::apply (const Slice &data, const Imath::Box2i &dataWindow) const +HalfLut::apply (const Slice &data, const IMATH_NAMESPACE::Box2i &dataWindow) const { assert (data.type == HALF); assert (dataWindow.min.x % data.xSampling == 0); @@ -71,24 +72,24 @@ HalfLut::apply (const Slice &data, const Imath::Box2i &dataWindow) const assert ((dataWindow.max.y - dataWindow.min.y + 1) % data.ySampling == 0); char *base = data.base + data.yStride * - (dataWindow.min.y / data.ySampling); + (dataWindow.min.y / data.ySampling); for (int y = dataWindow.min.y; - y <= dataWindow.max.y; - y += data.ySampling) - { - char *pixel = base + data.xStride * - (dataWindow.min.x / data.xSampling); - - for (int x = dataWindow.min.x; - x <= dataWindow.max.x; - x += data.xSampling) + y <= dataWindow.max.y; + y += data.ySampling) { - *(half *)pixel = _lut (*(half *)pixel); - pixel += data.xStride; - } - - base += data.yStride; + char *pixel = base + data.xStride * + (dataWindow.min.x / data.xSampling); + + for (int x = dataWindow.min.x; + x <= dataWindow.max.x; + x += data.xSampling) + { + *(half *)pixel = _lut (*(half *)pixel); + pixel += data.xStride; + } + + base += data.yStride; } } @@ -98,53 +99,53 @@ RgbaLut::apply (Rgba *data, int nData, int stride) const { while (nData) { - if (_chn & WRITE_R) - data->r = _lut (data->r); + if (_chn & WRITE_R) + data->r = _lut (data->r); - if (_chn & WRITE_G) - data->g = _lut (data->g); + if (_chn & WRITE_G) + data->g = _lut (data->g); - if (_chn & WRITE_B) - data->b = _lut (data->b); + if (_chn & WRITE_B) + data->b = _lut (data->b); - if (_chn & WRITE_A) - data->a = _lut (data->a); + if (_chn & WRITE_A) + data->a = _lut (data->a); - data += stride; - nData -= 1; + data += stride; + nData -= 1; } } void RgbaLut::apply (Rgba *base, - int xStride, int yStride, - const Imath::Box2i &dataWindow) const + int xStride, int yStride, + const IMATH_NAMESPACE::Box2i &dataWindow) const { base += dataWindow.min.y * yStride; for (int y = dataWindow.min.y; y <= dataWindow.max.y; ++y) { - Rgba *pixel = base + dataWindow.min.x * xStride; + Rgba *pixel = base + dataWindow.min.x * xStride; - for (int x = dataWindow.min.x; x <= dataWindow.max.x; ++x) - { - if (_chn & WRITE_R) - pixel->r = _lut (pixel->r); + for (int x = dataWindow.min.x; x <= dataWindow.max.x; ++x) + { + if (_chn & WRITE_R) + pixel->r = _lut (pixel->r); - if (_chn & WRITE_G) - pixel->g = _lut (pixel->g); + if (_chn & WRITE_G) + pixel->g = _lut (pixel->g); - if (_chn & WRITE_B) - pixel->b = _lut (pixel->b); + if (_chn & WRITE_B) + pixel->b = _lut (pixel->b); - if (_chn & WRITE_A) - pixel->a = _lut (pixel->a); + if (_chn & WRITE_A) + pixel->a = _lut (pixel->a); - pixel += xStride; - } + pixel += xStride; + } - base += yStride; + base += yStride; } } @@ -157,20 +158,21 @@ round12log (half x) if (x <= 0) { - return 0; + return 0; } else { - int12log = int (2000.5 + 200.0 * log (x / middleval) / log (2.0)); + int12log = int (2000.5 + 200.0 * log (x / middleval) / log (2.0)); - if (int12log > 4095) - int12log = 4095; + if (int12log > 4095) + int12log = 4095; - if (int12log < 1) - int12log = 1; + if (int12log < 1) + int12log = 1; } return middleval * pow (2.0, (int12log - 2000.0) / 200.0); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT + diff --git a/3rdparty/openexr/IlmImf/ImfLut.h b/3rdparty/openexr/IlmImf/ImfLut.h index 6ad7384154..c59beabfa3 100644 --- a/3rdparty/openexr/IlmImf/ImfLut.h +++ b/3rdparty/openexr/IlmImf/ImfLut.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,12 +45,14 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfRgbaFile.h" +#include "ImfFrameBuffer.h" #include "ImathBox.h" #include "halfFunction.h" +#include "ImfNamespace.h" +#include "ImfExport.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER // // Lookup table for individual half channels. @@ -72,17 +74,19 @@ class HalfLut // Apply the table to data[0], data[stride] ... data[(nData-1) * stride] //---------------------------------------------------------------------- + IMF_EXPORT void apply (half *data, - int nData, - int stride = 1) const; + int nData, + int stride = 1) const; //--------------------------------------------------------------- // Apply the table to a frame buffer slice (see ImfFrameBuffer.h) //--------------------------------------------------------------- + IMF_EXPORT void apply (const Slice &data, - const Imath::Box2i &dataWindow) const; + const IMATH_NAMESPACE::Box2i &dataWindow) const; private: @@ -110,19 +114,21 @@ class RgbaLut // Apply the table to data[0], data[stride] ... data[(nData-1) * stride] //---------------------------------------------------------------------- + IMF_EXPORT void apply (Rgba *data, - int nData, - int stride = 1) const; + int nData, + int stride = 1) const; //----------------------------------------------------------------------- // Apply the table to a frame buffer (see RgbaOutpuFile.setFrameBuffer()) //----------------------------------------------------------------------- + IMF_EXPORT void apply (Rgba *base, - int xStride, - int yStride, - const Imath::Box2i &dataWindow) const; + int xStride, + int yStride, + const IMATH_NAMESPACE::Box2i &dataWindow) const; private: @@ -139,6 +145,7 @@ class RgbaLut // the center [2000] and that number is near 0.18. // +IMF_EXPORT half round12log (half x); @@ -164,7 +171,7 @@ struct roundNBit template HalfLut::HalfLut (Function f): _lut(f, -HALF_MAX, HALF_MAX, half (0), - half::posInf(), half::negInf(), half::qNan()) + half::posInf(), half::negInf(), half::qNan()) { // empty } @@ -173,13 +180,13 @@ HalfLut::HalfLut (Function f): template RgbaLut::RgbaLut (Function f, RgbaChannels chn): _lut(f, -HALF_MAX, HALF_MAX, half (0), - half::posInf(), half::negInf(), half::qNan()), + half::posInf(), half::negInf(), half::qNan()), _chn(chn) { // empty } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfMatrixAttribute.cpp b/3rdparty/openexr/IlmImf/ImfMatrixAttribute.cpp index 0010e20b1a..84efe7e239 100644 --- a/3rdparty/openexr/IlmImf/ImfMatrixAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfMatrixAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,7 +46,10 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + + +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> @@ -59,7 +62,7 @@ M33fAttribute::staticTypeName () template <> void -M33fAttribute::writeValueTo (OStream &os, int) const +M33fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value[0][0]); Xdr::write (os, _value[0][1]); @@ -77,7 +80,7 @@ M33fAttribute::writeValueTo (OStream &os, int) const template <> void -M33fAttribute::readValueFrom (IStream &is, int, int) +M33fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value[0][0]); Xdr::read (is, _value[0][1]); @@ -103,7 +106,7 @@ M33dAttribute::staticTypeName () template <> void -M33dAttribute::writeValueTo (OStream &os, int) const +M33dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value[0][0]); Xdr::write (os, _value[0][1]); @@ -121,7 +124,7 @@ M33dAttribute::writeValueTo (OStream &os, int) const template <> void -M33dAttribute::readValueFrom (IStream &is, int, int) +M33dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value[0][0]); Xdr::read (is, _value[0][1]); @@ -147,7 +150,7 @@ M44fAttribute::staticTypeName () template <> void -M44fAttribute::writeValueTo (OStream &os, int) const +M44fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value[0][0]); Xdr::write (os, _value[0][1]); @@ -173,7 +176,7 @@ M44fAttribute::writeValueTo (OStream &os, int) const template <> void -M44fAttribute::readValueFrom (IStream &is, int, int) +M44fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value[0][0]); Xdr::read (is, _value[0][1]); @@ -207,7 +210,7 @@ M44dAttribute::staticTypeName () template <> void -M44dAttribute::writeValueTo (OStream &os, int) const +M44dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value[0][0]); Xdr::write (os, _value[0][1]); @@ -233,7 +236,7 @@ M44dAttribute::writeValueTo (OStream &os, int) const template <> void -M44dAttribute::readValueFrom (IStream &is, int, int) +M44dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value[0][0]); Xdr::read (is, _value[0][1]); @@ -257,4 +260,4 @@ M44dAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfMatrixAttribute.h b/3rdparty/openexr/IlmImf/ImfMatrixAttribute.h index 7337254172..31f14668db 100644 --- a/3rdparty/openexr/IlmImf/ImfMatrixAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfMatrixAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,42 +46,38 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfAttribute.h" #include "ImathMatrix.h" +#include "ImfExport.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -typedef TypedAttribute M33fAttribute; -template <> const char *M33fAttribute::staticTypeName (); -template <> void M33fAttribute::writeValueTo (OStream &, int) const; -template <> void M33fAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute M33fAttribute; +template <> IMF_EXPORT const char *M33fAttribute::staticTypeName (); +template <> IMF_EXPORT void M33fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void M33fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute M33dAttribute; -template <> const char *M33dAttribute::staticTypeName (); -template <> void M33dAttribute::writeValueTo (OStream &, int) const; -template <> void M33dAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute M33dAttribute; +template <> IMF_EXPORT const char *M33dAttribute::staticTypeName (); +template <> IMF_EXPORT void M33dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void M33dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute M44fAttribute; -template <> const char *M44fAttribute::staticTypeName (); -template <> void M44fAttribute::writeValueTo (OStream &, int) const; -template <> void M44fAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute M44fAttribute; +template <> IMF_EXPORT const char *M44fAttribute::staticTypeName (); +template <> IMF_EXPORT void M44fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void M44fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute M44dAttribute; -template <> const char *M44dAttribute::staticTypeName (); -template <> void M44dAttribute::writeValueTo (OStream &, int) const; -template <> void M44dAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute M44dAttribute; +template <> IMF_EXPORT const char *M44dAttribute::staticTypeName (); +template <> IMF_EXPORT void M44dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void M44dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -} // namespace Imf - -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfMisc.cpp b/3rdparty/openexr/IlmImf/ImfMisc.cpp index 27f4cafc32..4622c41707 100644 --- a/3rdparty/openexr/IlmImf/ImfMisc.cpp +++ b/3rdparty/openexr/IlmImf/ImfMisc.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -49,12 +50,15 @@ #include #include #include +#include +#include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -using Imath::Box2i; -using Imath::divp; -using Imath::modp; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::divp; +using IMATH_NAMESPACE::modp; using std::vector; int @@ -64,24 +68,24 @@ pixelTypeSize (PixelType type) switch (type) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + size = Xdr::size (); + break; - size = Xdr::size (); - break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: - case HALF: + size = Xdr::size (); + break; - size = Xdr::size (); - break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: - case FLOAT: - - size = Xdr::size (); - break; + size = Xdr::size (); + break; default: - throw Iex::ArgExc ("Unknown pixel type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel type."); } return size; @@ -99,7 +103,7 @@ numSamples (int s, int a, int b) size_t bytesPerLineTable (const Header &header, - vector &bytesPerLine) + vector &bytesPerLine) { const Box2i &dataWindow = header.dataWindow(); const ChannelList &channels = header.channels(); @@ -107,48 +111,143 @@ bytesPerLineTable (const Header &header, bytesPerLine.resize (dataWindow.max.y - dataWindow.min.y + 1); for (ChannelList::ConstIterator c = channels.begin(); - c != channels.end(); - ++c) + c != channels.end(); + ++c) { - int nBytes = pixelTypeSize (c.channel().type) * - (dataWindow.max.x - dataWindow.min.x + 1) / - c.channel().xSampling; + int nBytes = pixelTypeSize (c.channel().type) * + (dataWindow.max.x - dataWindow.min.x + 1) / + c.channel().xSampling; - for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i) - if (modp (y, c.channel().ySampling) == 0) - bytesPerLine[i] += nBytes; + for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i) + if (modp (y, c.channel().ySampling) == 0) + bytesPerLine[i] += nBytes; } size_t maxBytesPerLine = 0; for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i) - if (maxBytesPerLine < bytesPerLine[i]) - maxBytesPerLine = bytesPerLine[i]; + if (maxBytesPerLine < bytesPerLine[i]) + maxBytesPerLine = bytesPerLine[i]; return maxBytesPerLine; } +static int +roundToNextMultiple(int n, int d) +{ + return ((n + d - 1) / d) * d; +} + +static int +roundToPrevMultiple(int n, int d) +{ + return (n / d) * d; +} + +size_t +bytesPerDeepLineTable (const Header &header, + int minY, int maxY, + const char* base, + int xStride, + int yStride, + vector &bytesPerLine) +{ + const Box2i &dataWindow = header.dataWindow(); + const ChannelList &channels = header.channels(); + + for (ChannelList::ConstIterator c = channels.begin(); + c != channels.end(); + ++c) + { + const int ySampling = abs(c.channel().ySampling); + const int xSampling = abs(c.channel().xSampling); + const int pixelSize = pixelTypeSize (c.channel().type); + + // Here we transform from the domain over all pixels into the domain + // of actual samples. We want to sample points in [minY, maxY] where + // (y % ySampling) == 0. However, doing this by rejecting samples + // requires O(height*width) modulo computations, which were a + // significant bottleneck in the previous implementation of this + // function. For the low, low price of 4 divisions per channel, we + // can tighten the y & x ranges to the least and greatest roots of the + // sampling function and then stride by the sampling rate. + const int sampleMinY = roundToNextMultiple(minY, ySampling); + const int sampleMaxY = roundToPrevMultiple(maxY, ySampling); + const int sampleMinX = roundToNextMultiple(dataWindow.min.x, xSampling); + const int sampleMaxX = roundToPrevMultiple(dataWindow.max.x, xSampling); + + for (int y = sampleMinY; y <= sampleMaxY; y+=ySampling) + { + int nBytes = 0; + for (int x = sampleMinX; x <= sampleMaxX; x += xSampling) + { + nBytes += pixelSize * + sampleCount(base, xStride, yStride, x, y); + } + bytesPerLine[y - dataWindow.min.y] += nBytes; + } + } + + size_t maxBytesPerLine = 0; + + for (int y = minY; y <= maxY; ++y) + if (maxBytesPerLine < bytesPerLine[y - dataWindow.min.y]) + maxBytesPerLine = bytesPerLine[y - dataWindow.min.y]; + + return maxBytesPerLine; +} + + +size_t +bytesPerDeepLineTable (const Header &header, + char* base, + int xStride, + int yStride, + vector &bytesPerLine) +{ + return bytesPerDeepLineTable(header, + header.dataWindow().min.y, + header.dataWindow().max.y, + base, + xStride, + yStride, + bytesPerLine); +} + void offsetInLineBufferTable (const vector &bytesPerLine, - int linesInLineBuffer, - vector &offsetInLineBuffer) + int scanline1, int scanline2, + int linesInLineBuffer, + vector &offsetInLineBuffer) { offsetInLineBuffer.resize (bytesPerLine.size()); size_t offset = 0; - for (int i = 0; i < bytesPerLine.size(); ++i) + for (int i = scanline1; i <= scanline2; ++i) { - if (i % linesInLineBuffer == 0) - offset = 0; + if (i % linesInLineBuffer == 0) + offset = 0; - offsetInLineBuffer[i] = offset; - offset += bytesPerLine[i]; + offsetInLineBuffer[i] = offset; + offset += bytesPerLine[i]; } } +void +offsetInLineBufferTable (const vector &bytesPerLine, + int linesInLineBuffer, + vector &offsetInLineBuffer) +{ + offsetInLineBufferTable (bytesPerLine, + 0, bytesPerLine.size() - 1, + linesInLineBuffer, + offsetInLineBuffer); +} + + int lineBufferMinY (int y, int minY, int linesInLineBuffer) { @@ -179,11 +278,11 @@ numLinesInBuffer (Compressor * compressor) void copyIntoFrameBuffer (const char *& readPtr, - char * writePtr, - char * endPtr, + char * writePtr, + char * endPtr, size_t xStride, - bool fill, - double fillValue, + bool fill, + double fillValue, Compressor::Format format, PixelType typeInFrameBuffer, PixelType typeInFile) @@ -202,8 +301,8 @@ copyIntoFrameBuffer (const char *& readPtr, switch (typeInFrameBuffer) { - case UINT: - + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + { unsigned int fillVal = (unsigned int) (fillValue); @@ -215,7 +314,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: { half fillVal = half (fillValue); @@ -228,7 +327,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: { float fillVal = float (fillValue); @@ -243,7 +342,7 @@ copyIntoFrameBuffer (const char *& readPtr, default: - throw Iex::ArgExc ("Unknown pixel data type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } else if (format == Compressor::XDR) @@ -258,11 +357,11 @@ copyIntoFrameBuffer (const char *& readPtr, switch (typeInFrameBuffer) { - case UINT: - + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + switch (typeInFile) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: while (writePtr <= endPtr) { @@ -271,7 +370,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: while (writePtr <= endPtr) { @@ -282,7 +381,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: while (writePtr <= endPtr) { @@ -292,14 +391,17 @@ copyIntoFrameBuffer (const char *& readPtr, writePtr += xStride; } break; + + default: + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: switch (typeInFile) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: while (writePtr <= endPtr) { @@ -309,8 +411,8 @@ copyIntoFrameBuffer (const char *& readPtr, writePtr += xStride; } break; - - case HALF: + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: while (writePtr <= endPtr) { @@ -319,7 +421,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: while (writePtr <= endPtr) { @@ -329,14 +431,17 @@ copyIntoFrameBuffer (const char *& readPtr, writePtr += xStride; } break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: switch (typeInFile) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: while (writePtr <= endPtr) { @@ -347,7 +452,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: while (writePtr <= endPtr) { @@ -358,7 +463,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: while (writePtr <= endPtr) { @@ -366,12 +471,15 @@ copyIntoFrameBuffer (const char *& readPtr, writePtr += xStride; } break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } break; default: - throw Iex::ArgExc ("Unknown pixel data type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } else @@ -383,11 +491,11 @@ copyIntoFrameBuffer (const char *& readPtr, switch (typeInFrameBuffer) { - case UINT: - + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + switch (typeInFile) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: while (writePtr <= endPtr) { @@ -399,7 +507,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: while (writePtr <= endPtr) { @@ -410,7 +518,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: while (writePtr <= endPtr) { @@ -424,14 +532,18 @@ copyIntoFrameBuffer (const char *& readPtr, writePtr += xStride; } break; + + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: switch (typeInFile) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: while (writePtr <= endPtr) { @@ -446,17 +558,25 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case HALF: - - while (writePtr <= endPtr) - { - *(half *) writePtr = *(half *)readPtr; - readPtr += sizeof (half); - writePtr += xStride; + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + // If we're tightly packed, just memcpy + if (xStride == sizeof(half)) { + int numBytes = endPtr-writePtr+sizeof(half); + memcpy(writePtr, readPtr, numBytes); + readPtr += numBytes; + writePtr += numBytes; + } else { + while (writePtr <= endPtr) + { + *(half *) writePtr = *(half *)readPtr; + readPtr += sizeof (half); + writePtr += xStride; + } } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: while (writePtr <= endPtr) { @@ -470,14 +590,17 @@ copyIntoFrameBuffer (const char *& readPtr, writePtr += xStride; } break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: switch (typeInFile) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: while (writePtr <= endPtr) { @@ -492,7 +615,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: while (writePtr <= endPtr) { @@ -503,7 +626,7 @@ copyIntoFrameBuffer (const char *& readPtr, } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: while (writePtr <= endPtr) { @@ -514,12 +637,716 @@ copyIntoFrameBuffer (const char *& readPtr, writePtr += xStride; } break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + break; + + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + } +} + +void +copyIntoDeepFrameBuffer (const char *& readPtr, + char * base, + const char* sampleCountBase, + ptrdiff_t sampleCountXStride, + ptrdiff_t sampleCountYStride, + int y, int minX, int maxX, + int xOffsetForSampleCount, + int yOffsetForSampleCount, + int xOffsetForData, + int yOffsetForData, + ptrdiff_t sampleStride, + ptrdiff_t xPointerStride, + ptrdiff_t yPointerStride, + bool fill, + double fillValue, + Compressor::Format format, + PixelType typeInFrameBuffer, + PixelType typeInFile) +{ + // + // Copy a horizontal row of pixels from an input + // file's line or tile buffer to a frame buffer. + // + + if (fill) + { + // + // The file contains no data for this channel. + // Store a default value in the frame buffer. + // + + switch (typeInFrameBuffer) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + { + unsigned int fillVal = (unsigned int) (fillValue); + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + if(writePtr) + { + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + for (int i = 0; i < count; i++) + { + *(unsigned int *) writePtr = fillVal; + writePtr += sampleStride; + } + } + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + { + half fillVal = half (fillValue); + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + if(writePtr) + { + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + for (int i = 0; i < count; i++) + { + *(half *) writePtr = fillVal; + writePtr += sampleStride; + } + } + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + { + float fillVal = float (fillValue); + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + if(writePtr) + { + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + for (int i = 0; i < count; i++) + { + *(float *) writePtr = fillVal; + writePtr += sampleStride; + } + } + } + } + break; + + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + } + else if (format == Compressor::XDR) + { + // + // The the line or tile buffer is in XDR format. + // + // Convert the pixels from the file's machine- + // independent representation, and store the + // results in the frame buffer. + // + + switch (typeInFrameBuffer) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + switch (typeInFile) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + if(writePtr) + { + + for (int i = 0; i < count; i++) + { + Xdr::read (readPtr, *(unsigned int *) writePtr); + writePtr += sampleStride; + } + }else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + if(writePtr) + { + + for (int i = 0; i < count; i++) + { + half h; + Xdr::read (readPtr, h); + *(unsigned int *) writePtr = halfToUint (h); + writePtr += sampleStride; + } + }else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + float f; + Xdr::read (readPtr, f); + *(unsigned int *)writePtr = floatToUint (f); + writePtr += sampleStride; + } + }else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + + } + break; + default: + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + switch (typeInFile) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + if(writePtr) + { + + for (int i = 0; i < count; i++) + { + unsigned int ui; + Xdr::read (readPtr, ui); + *(half *) writePtr = uintToHalf (ui); + writePtr += sampleStride; + } + }else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + if(writePtr) + { + + for (int i = 0; i < count; i++) + { + Xdr::read (readPtr, *(half *) writePtr); + writePtr += sampleStride; + } + }else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **) (base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + if(writePtr) + { + for (int i = 0; i < count; i++) + { + float f; + Xdr::read (readPtr, f); + *(half *) writePtr = floatToHalf (f); + writePtr += sampleStride; + } + }else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + } + break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + switch (typeInFile) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + if(writePtr) + { + for (int i = 0; i < count; i++) + { + unsigned int ui; + Xdr::read (readPtr, ui); + *(float *) writePtr = float (ui); + writePtr += sampleStride; + } + }else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + if(writePtr) + { + + for (int i = 0; i < count; i++) + { + half h; + Xdr::read (readPtr, h); + *(float *) writePtr = float (h); + writePtr += sampleStride; + } + + }else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + if(writePtr) + { + + for (int i = 0; i < count; i++) + { + Xdr::read (readPtr, *(float *) writePtr); + writePtr += sampleStride; + } + } else{ + Xdr::skip (readPtr,count*Xdr::size()); + } + + } + break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + break; + + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + } + else + { + // + // The the line or tile buffer is in NATIVE format. + // Copy the results into the frame buffer. + // + + switch (typeInFrameBuffer) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + switch (typeInFile) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + for (size_t i = 0; i < sizeof (unsigned int); ++i) + writePtr[i] = readPtr[i]; + + readPtr += sizeof (unsigned int); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(unsigned int)*count; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + half h = *(half *) readPtr; + *(unsigned int *) writePtr = halfToUint (h); + readPtr += sizeof (half); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(half)*count; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + + for (int i = 0; i < count; i++) + { + float f; + + for (size_t i = 0; i < sizeof (float); ++i) + ((char *)&f)[i] = readPtr[i]; + + *(unsigned int *)writePtr = floatToUint (f); + readPtr += sizeof (float); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(float)*count; + } + } + break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + switch (typeInFile) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + unsigned int ui; + + for (size_t i = 0; i < sizeof (unsigned int); ++i) + ((char *)&ui)[i] = readPtr[i]; + + *(half *) writePtr = uintToHalf (ui); + readPtr += sizeof (unsigned int); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(unsigned int)*count; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + *(half *) writePtr = *(half *)readPtr; + readPtr += sizeof (half); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(half)*count; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + float f; + + for (size_t i = 0; i < sizeof (float); ++i) + ((char *)&f)[i] = readPtr[i]; + + *(half *) writePtr = floatToHalf (f); + readPtr += sizeof (float); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(float)*count; + } + } + break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + switch (typeInFile) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + unsigned int ui; + + for (size_t i = 0; i < sizeof (unsigned int); ++i) + ((char *)&ui)[i] = readPtr[i]; + + *(float *) writePtr = float (ui); + readPtr += sizeof (unsigned int); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(unsigned int)*count; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + half h = *(half *) readPtr; + *(float *) writePtr = float (h); + readPtr += sizeof (half); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(half)*count; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (int x = minX; x <= maxX; x++) + { + char* writePtr = *(char **)(base+(y-yOffsetForData)*yPointerStride + (x-xOffsetForData)*xPointerStride); + + int count = sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + if(writePtr) + { + for (int i = 0; i < count; i++) + { + for (size_t i = 0; i < sizeof (float); ++i) + writePtr[i] = readPtr[i]; + + readPtr += sizeof (float); + writePtr += sampleStride; + } + }else{ + readPtr+=sizeof(float)*count; + } + } + break; + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } break; default: - throw Iex::ArgExc ("Unknown pixel data type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } } @@ -528,28 +1355,28 @@ copyIntoFrameBuffer (const char *& readPtr, void skipChannel (const char *& readPtr, PixelType typeInFile, - size_t xSize) + size_t xSize) { switch (typeInFile) { - case UINT: - + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + Xdr::skip (readPtr, Xdr::size () * xSize); break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: Xdr::skip (readPtr, Xdr::size () * xSize); break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: Xdr::skip (readPtr, Xdr::size () * xSize); break; default: - throw Iex::ArgExc ("Unknown pixel data type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } @@ -557,52 +1384,52 @@ skipChannel (const char *& readPtr, void convertInPlace (char *& writePtr, const char *& readPtr, - PixelType type, + PixelType type, size_t numPixels) { switch (type) { - case UINT: - - for (int j = 0; j < numPixels; ++j) + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (size_t j = 0; j < numPixels; ++j) { Xdr::write (writePtr, *(const unsigned int *) readPtr); readPtr += sizeof(unsigned int); } break; - - case HALF: - - for (int j = 0; j < numPixels; ++j) - { + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (size_t j = 0; j < numPixels; ++j) + { Xdr::write (writePtr, *(const half *) readPtr); readPtr += sizeof(half); } break; - - case FLOAT: - - for (int j = 0; j < numPixels; ++j) + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (size_t j = 0; j < numPixels; ++j) { Xdr::write (writePtr, *(const float *) readPtr); readPtr += sizeof(float); } break; - + default: - - throw Iex::ArgExc ("Unknown pixel data type."); + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } void copyFromFrameBuffer (char *& writePtr, - const char *& readPtr, + const char *& readPtr, const char * endPtr, - size_t xStride, + size_t xStride, Compressor::Format format, - PixelType type) + PixelType type) { // // Copy a horizontal row of pixels from a frame @@ -617,7 +1444,7 @@ copyFromFrameBuffer (char *& writePtr, switch (type) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: while (readPtr <= endPtr) { @@ -627,7 +1454,7 @@ copyFromFrameBuffer (char *& writePtr, } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: while (readPtr <= endPtr) { @@ -636,7 +1463,7 @@ copyFromFrameBuffer (char *& writePtr, } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: while (readPtr <= endPtr) { @@ -647,7 +1474,7 @@ copyFromFrameBuffer (char *& writePtr, default: - throw Iex::ArgExc ("Unknown pixel data type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } else @@ -658,7 +1485,7 @@ copyFromFrameBuffer (char *& writePtr, switch (type) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: while (readPtr <= endPtr) { @@ -669,7 +1496,7 @@ copyFromFrameBuffer (char *& writePtr, } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: while (readPtr <= endPtr) { @@ -679,7 +1506,7 @@ copyFromFrameBuffer (char *& writePtr, } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: while (readPtr <= endPtr) { @@ -689,10 +1516,189 @@ copyFromFrameBuffer (char *& writePtr, readPtr += xStride; } break; + + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + } +} + +void +copyFromDeepFrameBuffer (char *& writePtr, + const char * base, + char* sampleCountBase, + ptrdiff_t sampleCountXStride, + ptrdiff_t sampleCountYStride, + int y, int xMin, int xMax, + int xOffsetForSampleCount, + int yOffsetForSampleCount, + int xOffsetForData, + int yOffsetForData, + ptrdiff_t sampleStride, + ptrdiff_t dataXStride, + ptrdiff_t dataYStride, + Compressor::Format format, + PixelType type) +{ + // + // Copy a horizontal row of pixels from a frame + // buffer to an output file's line or tile buffer. + // + + if (format == Compressor::XDR) + { + // + // The the line or tile buffer is in XDR format. + // + + switch (type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (int x = xMin; x <= xMax; x++) + { + unsigned int count = + sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + const char* ptr = base + (y-yOffsetForData) * dataYStride + (x-xOffsetForData) * dataXStride; + const char* readPtr = ((const char**) ptr)[0]; + for (unsigned int i = 0; i < count; i++) + { + Xdr::write (writePtr, + *(const unsigned int *) readPtr); + readPtr += sampleStride; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (int x = xMin; x <= xMax; x++) + { + unsigned int count = + sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + const char* ptr = base + (y-yOffsetForData) * dataYStride + (x-xOffsetForData) * dataXStride; + const char* readPtr = ((const char**) ptr)[0]; + for (unsigned int i = 0; i < count; i++) + { + Xdr::write (writePtr, *(const half *) readPtr); + readPtr += sampleStride; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (int x = xMin; x <= xMax; x++) + { + unsigned int count = + sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + const char* ptr = base + (y-yOffsetForData) * dataYStride + (x-xOffsetForData) * dataXStride; + + const char* readPtr = ((const char**) ptr)[0]; + for (unsigned int i = 0; i < count; i++) + { + Xdr::write (writePtr, *(const float *) readPtr); + readPtr += sampleStride; + } + } + break; default: - throw Iex::ArgExc ("Unknown pixel data type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); + } + } + else + { + // + // The the line or tile buffer is in NATIVE format. + // + + switch (type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: + + for (int x = xMin; x <= xMax; x++) + { + unsigned int count = + sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + const char* ptr = base + (y-yOffsetForData) * dataYStride + (x-xOffsetForData) * dataXStride; + const char* readPtr = ((const char**) ptr)[0]; + for (unsigned int i = 0; i < count; i++) + { + for (size_t j = 0; j < sizeof (unsigned int); ++j) + *writePtr++ = readPtr[j]; + + readPtr += sampleStride; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: + + for (int x = xMin; x <= xMax; x++) + { + unsigned int count = + sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + const char* ptr = base + (y-yOffsetForData) * dataYStride + (x-xOffsetForData) * dataXStride; + const char* readPtr = ((const char**) ptr)[0]; + for (unsigned int i = 0; i < count; i++) + { + *(half *) writePtr = *(const half *) readPtr; + writePtr += sizeof (half); + readPtr += sampleStride; + } + } + break; + + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: + + for (int x = xMin; x <= xMax; x++) + { + unsigned int count = + sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x - xOffsetForSampleCount, + y - yOffsetForSampleCount); + + const char* ptr = base + (y-yOffsetForData) * dataYStride + (x-xOffsetForData) * dataXStride; + const char* readPtr = ((const char**) ptr)[0]; + for (unsigned int i = 0; i < count; i++) + { + for (size_t j = 0; j < sizeof (float); ++j) + *writePtr++ = readPtr[j]; + + readPtr += sampleStride; + } + } + break; + + default: + + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } } @@ -700,9 +1706,9 @@ copyFromFrameBuffer (char *& writePtr, void fillChannelWithZeroes (char *& writePtr, - Compressor::Format format, - PixelType type, - size_t xSize) + Compressor::Format format, + PixelType type, + size_t xSize) { if (format == Compressor::XDR) { @@ -712,30 +1718,30 @@ fillChannelWithZeroes (char *& writePtr, switch (type) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: - for (int j = 0; j < xSize; ++j) + for (size_t j = 0; j < xSize; ++j) Xdr::write (writePtr, (unsigned int) 0); break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: - for (int j = 0; j < xSize; ++j) + for (size_t j = 0; j < xSize; ++j) Xdr::write (writePtr, (half) 0); break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: - for (int j = 0; j < xSize; ++j) + for (size_t j = 0; j < xSize; ++j) Xdr::write (writePtr, (float) 0); break; - + default: - throw Iex::ArgExc ("Unknown pixel data type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } else @@ -746,9 +1752,9 @@ fillChannelWithZeroes (char *& writePtr, switch (type) { - case UINT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: - for (int j = 0; j < xSize; ++j) + for (size_t j = 0; j < xSize; ++j) { static const unsigned int ui = 0; @@ -757,18 +1763,18 @@ fillChannelWithZeroes (char *& writePtr, } break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: - for (int j = 0; j < xSize; ++j) + for (size_t j = 0; j < xSize; ++j) { *(half *) writePtr = half (0); writePtr += sizeof (half); } break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: - for (int j = 0; j < xSize; ++j) + for (size_t j = 0; j < xSize; ++j) { static const float f = 0; @@ -776,12 +1782,98 @@ fillChannelWithZeroes (char *& writePtr, *writePtr++ = ((char *) &f)[i]; } break; - + default: - throw Iex::ArgExc ("Unknown pixel data type."); + throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); } } } -} // namespace Imf +bool +usesLongNames (const Header &header) +{ + // + // If an OpenEXR file contains any attribute names, attribute type names + // or channel names longer than 31 characters, then the file cannot be + // read by older versions of the IlmImf library (up to OpenEXR 1.6.1). + // Before writing the file header, we check if the header contains + // any names longer than 31 characters; if it does, then we set the + // LONG_NAMES_FLAG in the file version number. Older versions of the + // IlmImf library will refuse to read files that have the LONG_NAMES_FLAG + // set. Without the flag, older versions of the library would mis- + // interpret the file as broken. + // + + for (Header::ConstIterator i = header.begin(); + i != header.end(); + ++i) + { + if (strlen (i.name()) >= 32 || strlen (i.attribute().typeName()) >= 32) + return true; + } + + const ChannelList &channels = header.channels(); + + for (ChannelList::ConstIterator i = channels.begin(); + i != channels.end(); + ++i) + { + if (strlen (i.name()) >= 32) + return true; + } + + return false; +} + +int +getScanlineChunkOffsetTableSize(const Header& header) +{ + const Box2i &dataWindow = header.dataWindow(); + + vector bytesPerLine; + size_t maxBytesPerLine = bytesPerLineTable (header, + bytesPerLine); + + Compressor* compressor = newCompressor(header.compression(), + maxBytesPerLine, + header); + + int linesInBuffer = numLinesInBuffer (compressor); + + int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y + + linesInBuffer) / linesInBuffer; + + delete compressor; + + return lineOffsetSize; +} + +// +// Located in ImfTiledMisc.cpp +// +int +getTiledChunkOffsetTableSize(const Header& header); + +int +getChunkOffsetTableSize(const Header& header,bool ignore_attribute) +{ + if(!ignore_attribute && header.hasChunkCount()) + { + return header.chunkCount(); + } + + if(header.hasType() && !isSupportedType(header.type())) + { + throw IEX_NAMESPACE::ArgExc ("unsupported header type to " + "get chunk offset table size"); + } + if (isTiled(header.type()) == false) + return getScanlineChunkOffsetTableSize(header); + else + return getTiledChunkOffsetTableSize(header); + +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfMisc.h b/3rdparty/openexr/IlmImf/ImfMisc.h index 3a464a03da..c0d90eaa1b 100644 --- a/3rdparty/openexr/IlmImf/ImfMisc.h +++ b/3rdparty/openexr/IlmImf/ImfMisc.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,19 +43,26 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfPixelType.h" +#include "ImfCompressor.h" +#include "ImfArray.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" + +#include #include -#include -namespace Imf { -class Header; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + // // Return the size of a single value of the indicated type, // in the machine's native format. // +IMF_EXPORT int pixelTypeSize (PixelType type); @@ -67,6 +74,7 @@ int pixelTypeSize (PixelType type); // interval [2, 6]. // +IMF_EXPORT int numSamples (int s, int a, int b); @@ -77,22 +85,91 @@ int numSamples (int s, int a, int b); // the pixel data are tightly packed). // +IMF_EXPORT size_t bytesPerLineTable (const Header &header, - std::vector &bytesPerLine); + std::vector &bytesPerLine); + + +// +// Get the sample count for pixel (x, y) using the array base +// pointer, xStride and yStride. +// + +inline +int& +sampleCount(char* base, int xStride, int yStride, int x, int y) +{ + char* ptr = base + y * yStride + x * xStride; + int* intPtr = (int*) ptr; + + return *intPtr; +} + + +inline +const int& +sampleCount(const char* base, int xStride, int yStride, int x, int y) +{ + const char* ptr = base + y * yStride + x * xStride; + int* intPtr = (int*) ptr; + + return *intPtr; +} + +// +// Build a table that lists, for each scanline in a DEEP file's +// data window, how many bytes are required to store all +// pixels in all channels in scanlines ranged in [minY, maxY] +// (assuming that the pixel data are tightly packed). +// + +IMF_EXPORT +size_t bytesPerDeepLineTable (const Header &header, + int minY, int maxY, + const char* base, + int xStride, + int yStride, + std::vector &bytesPerLine); + + +// +// Build a table that lists, for each scanline in a DEEP file's +// data window, how many bytes are required to store all +// pixels in all channels in every scanline (assuming that +// the pixel data are tightly packed). +// + +IMF_EXPORT +size_t bytesPerDeepLineTable (const Header &header, + char* base, + int xStride, + int yStride, + std::vector &bytesPerLine); + // // For scanline-based files, pixels are read or written in // in multi-scanline blocks. Internally, class OutputFile // and class ScanLineInputFile store a block of scan lines // in a "line buffer". Function offsetInLineBufferTable() -// builds a table that lists, for each scan line in a file's -// data window, the location of the pixel data for the scanline -// relative to the beginning of the line buffer. +// builds a table that lists, scanlines within range +// [scanline1, scanline2], the location of the pixel data +// for the scanline relative to the beginning of the line buffer, +// where scanline1 = 0 represents the first line in the DATA WINDOW. +// The one without specifying the range will make scanline1 = 0 +// and scanline2 = bytesPerLine.size(). // +IMF_EXPORT +void offsetInLineBufferTable (const std::vector &bytesPerLine, + int scanline1, int scanline2, + int linesInLineBuffer, + std::vector &offsetInLineBuffer); + +IMF_EXPORT void offsetInLineBufferTable (const std::vector &bytesPerLine, - int linesInLineBuffer, - std::vector &offsetInLineBuffer); + int linesInLineBuffer, + std::vector &offsetInLineBuffer); // // For a scanline-based file, compute the range of scanlines @@ -100,8 +177,8 @@ void offsetInLineBufferTable (const std::vector &bytesPerLine, // (minY is the minimum y coordinate of the file's data window.) // -int lineBufferMinY (int y, int minY, int linesInLineBuffer); -int lineBufferMaxY (int y, int minY, int linesInLineBuffer); +IMF_EXPORT int lineBufferMinY (int y, int minY, int linesInLineBuffer); +IMF_EXPORT int lineBufferMaxY (int y, int minY, int linesInLineBuffer); // @@ -109,6 +186,7 @@ int lineBufferMaxY (int y, int minY, int linesInLineBuffer); // If compressor is 0, return Compressor::XDR. // +IMF_EXPORT Compressor::Format defaultFormat (Compressor *compressor); @@ -117,6 +195,7 @@ Compressor::Format defaultFormat (Compressor *compressor); // or uncompress at once. If compressor is 0, return 1. // +IMF_EXPORT int numLinesInBuffer (Compressor *compressor); @@ -146,16 +225,79 @@ int numLinesInBuffer (Compressor *compressor); // typeInFile the pixel data type in the input file's channel // +IMF_EXPORT void copyIntoFrameBuffer (const char *&readPtr, - char *writePtr, + char *writePtr, char *endPtr, - size_t xStride, - bool fill, + size_t xStride, + bool fill, double fillValue, - Compressor::Format format, + Compressor::Format format, PixelType typeInFrameBuffer, PixelType typeInFile); + +// +// Copy a single channel of a horizontal row of pixels from an +// input file's internal line buffer or tile buffer into a +// frame buffer slice. If necessary, perform on-the-fly data +// type conversion. +// +// readPtr initially points to the beginning of the +// data in the line or tile buffer. readPtr +// is advanced as the pixel data are copied; +// when copyIntoFrameBuffer() returns, +// readPtr points just past the end of the +// copied data. +// +// base point to each pixel in the framebuffer +// +// sampleCountBase, provide the number of samples in each pixel +// sampleCountXStride, +// sampleCountYStride +// +// y the scanline to copy. The coordinate is +// relative to the datawindow.min.y. +// +// minX, maxX used to indicate which pixels in the scanline +// will be copied. +// +// xOffsetForSampleCount, used to offset the sample count array +// yOffsetForSampleCount, and the base array. +// xOffsetForData, +// yOffsetForData +// +// xStride the xStride for the frame buffer slice +// +// format indicates if the line or tile buffer is +// in NATIVE or XDR format. +// +// typeInFrameBuffer the pixel data type of the frame buffer slice +// +// typeInFile the pixel data type in the input file's channel +// + +IMF_EXPORT +void copyIntoDeepFrameBuffer (const char *& readPtr, + char * base, + const char* sampleCountBase, + ptrdiff_t sampleCountXStride, + ptrdiff_t sampleCountYStride, + int y, int minX, int maxX, + int xOffsetForSampleCount, + int yOffsetForSampleCount, + int xOffsetForData, + int yOffsetForData, + ptrdiff_t xStride, + ptrdiff_t xPointerStride, + ptrdiff_t yPointerStride, + bool fill, + double fillValue, + Compressor::Format format, + PixelType typeInFrameBuffer, + PixelType typeInFile); + + // // Given a pointer into a an input file's line buffer or tile buffer, // skip over the data for xSize pixels of type typeInFile. @@ -164,9 +306,10 @@ void copyIntoFrameBuffer (const char *&readPtr, // skipped data. // +IMF_EXPORT void skipChannel (const char *&readPtr, - PixelType typeInFile, - size_t xSize); + PixelType typeInFile, + size_t xSize); // // Convert an array of pixel data from the machine's native @@ -185,11 +328,12 @@ void skipChannel (const char *&readPtr, // type the pixel data type // // numPixels number of pixels in the input and output arrays -// +// +IMF_EXPORT void convertInPlace (char *&toPtr, - const char *&fromPtr, - PixelType type, + const char *&fromPtr, + PixelType type, size_t numPixels); // @@ -218,12 +362,76 @@ void convertInPlace (char *&toPtr, // data type conversion) // +IMF_EXPORT void copyFromFrameBuffer (char *&writePtr, - const char *&readPtr, + const char *&readPtr, const char *endPtr, - size_t xStride, + size_t xStride, Compressor::Format format, - PixelType type); + PixelType type); + +// +// Copy a single channel of a horizontal row of pixels from a +// a frame buffer in a deep data file into an output file's +// internal line buffer or tile buffer. +// +// writePtr initially points to the beginning of the +// data in the line or tile buffer. writePtr +// is advanced as the pixel data are copied; +// when copyFromDeepFrameBuffer() returns, +// writePtr points just past the end of the +// copied data. +// +// base the start pointer of each pixel in this channel. +// It points to the real data in FrameBuffer. +// It is different for different channels. +// dataWindowMinX and dataWindowMinY are involved in +// locating for base. +// +// sampleCountBase, used to locate the position to get +// sampleCountXStride, the number of samples for each pixel. +// sampleCountYStride Used to determine how far we should +// read based on the pointer provided by base. +// +// y the scanline to copy. If we are dealing +// with a tiled deep file, then probably a portion +// of the scanline is copied. +// +// xMin, xMax used to indicate which pixels in the scanline +// will be copied. +// +// xOffsetForSampleCount, used to offset the sample count array +// yOffsetForSampleCount, and the base array. +// xOffsetForData, +// yOffsetForData +// +// xStride the xStride for the frame buffer slice +// +// format indicates if the line or tile buffer is +// in NATIVE or XDR format. +// +// type the pixel data type in the frame buffer +// and in the output file's channel (function +// copyFromFrameBuffer() doesn't do on-the-fly +// data type conversion) +// + +IMF_EXPORT +void copyFromDeepFrameBuffer (char *& writePtr, + const char * base, + char* sampleCountBase, + ptrdiff_t sampleCountXStride, + ptrdiff_t sampleCountYStride, + int y, int xMin, int xMax, + int xOffsetForSampleCount, + int yOffsetForSampleCount, + int xOffsetForData, + int yOffsetForData, + ptrdiff_t sampleStride, + ptrdiff_t xStrideForData, + ptrdiff_t yStrideForData, + Compressor::Format format, + PixelType type); // // Fill part of an output file's line buffer or tile buffer with @@ -245,11 +453,26 @@ void copyFromFrameBuffer (char *&writePtr, // xSize number of pixels to be filled with zeroes. // +IMF_EXPORT void fillChannelWithZeroes (char *&writePtr, - Compressor::Format format, - PixelType type, - size_t xSize); + Compressor::Format format, + PixelType type, + size_t xSize); + +IMF_EXPORT +bool usesLongNames (const Header &header); + + +// +// compute size of chunk offset table - if ignore_attribute set to true +// will compute from the image size and layout, rather than the attribute +// The default behaviour is to read the attribute +// + +IMF_EXPORT +int getChunkOffsetTableSize(const Header& header,bool ignore_attribute=false); + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imf #endif diff --git a/3rdparty/openexr/IlmImf/ImfMultiPartInputFile.cpp b/3rdparty/openexr/IlmImf/ImfMultiPartInputFile.cpp new file mode 100644 index 0000000000..55bdcaa1e4 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfMultiPartInputFile.cpp @@ -0,0 +1,783 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfMultiPartInputFile.h" + +#include "ImfTimeCodeAttribute.h" +#include "ImfChromaticitiesAttribute.h" +#include "ImfBoxAttribute.h" +#include "ImfFloatAttribute.h" +#include "ImfStdIO.h" +#include "ImfTileOffsets.h" +#include "ImfMisc.h" +#include "ImfTiledMisc.h" +#include "ImfInputStreamMutex.h" +#include "ImfInputPartData.h" +#include "ImfPartType.h" +#include "ImfInputFile.h" +#include "ImfScanLineInputFile.h" +#include "ImfTiledInputFile.h" +#include "ImfDeepScanLineInputFile.h" +#include "ImfDeepTiledInputFile.h" +#include "ImfVersion.h" + +#include +#include +#include + +#include +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using IMATH_NAMESPACE::Box2i; + +using std::vector; +using std::map; +using std::set; +using std::string; + +namespace +{ + // Controls whether we error out in the event of shared attribute + // inconsistency in the input file + static const bool strictSharedAttribute = true; +} + +struct MultiPartInputFile::Data: public InputStreamMutex +{ + int version; // Version of this file. + bool deleteStream; // If we should delete the stream during destruction. + vector parts; // Data to initialize Output files. + int numThreads; // Number of threads + bool reconstructChunkOffsetTable; // If we should reconstruct + // the offset table if it's broken. + std::map _inputFiles; + std::vector
_headers; + + + void chunkOffsetReconstruction(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, const std::vector& parts); + + void readChunkOffsetTables(bool reconstructChunkOffsetTable); + + bool checkSharedAttributesValues(const Header & src, + const Header & dst, + std::vector & conflictingAttributes) const; + + TileOffsets* createTileOffsets(const Header& header); + + InputPartData* getPart(int partNumber); + + Data (bool deleteStream, int numThreads, bool reconstructChunkOffsetTable): + InputStreamMutex(), + deleteStream (deleteStream), + numThreads (numThreads), + reconstructChunkOffsetTable(reconstructChunkOffsetTable) + { + } + + ~Data() + { + if (deleteStream) delete is; + + for (size_t i = 0; i < parts.size(); i++) + delete parts[i]; + } + + template + T* createInputPartT(int partNumber) + { + + } +}; + +MultiPartInputFile::MultiPartInputFile(const char fileName[], + int numThreads, + bool reconstructChunkOffsetTable): + _data(new Data(true, numThreads, reconstructChunkOffsetTable)) +{ + try + { + _data->is = new StdIFStream (fileName); + initialize(); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + delete _data; + + REPLACE_EXC (e, "Cannot read image file " + "\"" << fileName << "\". " << e.what()); + throw; + } + catch (...) + { + delete _data; + throw; + } +} + +MultiPartInputFile::MultiPartInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, + int numThreads, + bool reconstructChunkOffsetTable): + _data(new Data(false, numThreads, reconstructChunkOffsetTable)) +{ + try + { + _data->is = &is; + initialize(); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + delete _data; + + REPLACE_EXC (e, "Cannot read image file " + "\"" << is.fileName() << "\". " << e.what()); + throw; + } + catch (...) + { + delete _data; + throw; + } +} + +template +T* +MultiPartInputFile::getInputPart(int partNumber) +{ + Lock lock(*_data); + if (_data->_inputFiles.find(partNumber) == _data->_inputFiles.end()) + { + T* file = new T(_data->getPart(partNumber)); + _data->_inputFiles.insert(std::make_pair(partNumber, (GenericInputFile*) file)); + return file; + } + else return (T*) _data->_inputFiles[partNumber]; +} + + +template InputFile* MultiPartInputFile::getInputPart(int); +template TiledInputFile* MultiPartInputFile::getInputPart(int); +template DeepScanLineInputFile* MultiPartInputFile::getInputPart(int); +template DeepTiledInputFile* MultiPartInputFile::getInputPart(int); + +InputPartData* +MultiPartInputFile::getPart(int partNumber) +{ + return _data->getPart(partNumber); +} + + + +const Header & + MultiPartInputFile::header(int n) const +{ + return _data->_headers[n]; +} + + + +MultiPartInputFile::~MultiPartInputFile() +{ + for (map::iterator it = _data->_inputFiles.begin(); + it != _data->_inputFiles.end(); it++) + { + delete it->second; + } + + delete _data; +} + + +bool +MultiPartInputFile::Data::checkSharedAttributesValues(const Header & src, + const Header & dst, + vector & conflictingAttributes) const +{ + conflictingAttributes.clear(); + + bool conflict = false; + + // + // Display Window + // + if (src.displayWindow() != dst.displayWindow()) + { + conflict = true; + conflictingAttributes.push_back ("displayWindow"); + } + + + // + // Pixel Aspect Ratio + // + if (src.pixelAspectRatio() != dst.pixelAspectRatio()) + { + conflict = true; + conflictingAttributes.push_back ("pixelAspectRatio"); + } + + + // + // Timecode + // + const TimeCodeAttribute * srcTimeCode = src.findTypedAttribute< + TimeCodeAttribute> (TimeCodeAttribute::staticTypeName()); + const TimeCodeAttribute * dstTimeCode = dst.findTypedAttribute< + TimeCodeAttribute> (TimeCodeAttribute::staticTypeName()); + + if (dstTimeCode) + { + if ( (srcTimeCode && (srcTimeCode->value() != dstTimeCode->value())) || + (!srcTimeCode)) + { + conflict = true; + conflictingAttributes.push_back (TimeCodeAttribute::staticTypeName()); + } + } + + // + // Chromaticities + // + const ChromaticitiesAttribute * srcChrom = src.findTypedAttribute< + ChromaticitiesAttribute> (ChromaticitiesAttribute::staticTypeName()); + const ChromaticitiesAttribute * dstChrom = dst.findTypedAttribute< + ChromaticitiesAttribute> (ChromaticitiesAttribute::staticTypeName()); + + if (dstChrom) + { + if ( (srcChrom && (srcChrom->value() != dstChrom->value())) || + (!srcChrom)) + { + conflict = true; + conflictingAttributes.push_back (ChromaticitiesAttribute::staticTypeName()); + } + } + + + return conflict; +} + + +void +MultiPartInputFile::initialize() +{ + readMagicNumberAndVersionField(*_data->is, _data->version); + + bool multipart = isMultiPart(_data->version); + bool tiled = isTiled(_data->version); + + // + // Multipart files don't have and shouldn't have the tiled bit set. + // + + if (tiled && multipart) + throw IEX_NAMESPACE::InputExc ("Multipart files cannot have the tiled bit set"); + + + int pos = 0; + while (true) + { + Header header; + header.readFrom(*_data->is, _data->version); + + // + // If we read nothing then we stop reading. + // + + if (header.readsNothing()) + { + pos++; + break; + } + + _data->_headers.push_back(header); + + if(multipart == false) + break; + } + + // + // Perform usual check on headers. + // + + for (size_t i = 0; i < _data->_headers.size(); i++) + { + // + // Silently invent a type if the file is a single part regular image. + // + + if( _data->_headers[i].hasType() == false ) + { + if(multipart) + + throw IEX_NAMESPACE::ArgExc ("Every header in a multipart file should have a type"); + + _data->_headers[i].setType(tiled ? TILEDIMAGE : SCANLINEIMAGE); + } + else + { + + // + // Silently fix the header type if it's wrong + // (happens when a regular Image file written by EXR_2.0 is rewritten by an older library, + // so doesn't effect deep image types) + // + + if(!multipart && !isNonImage(_data->version)) + { + _data->_headers[i].setType(tiled ? TILEDIMAGE : SCANLINEIMAGE); + } + } + + + + if( _data->_headers[i].hasName() == false ) + { + if(multipart) + throw IEX_NAMESPACE::ArgExc ("Every header in a multipart file should have a name"); + } + + if (isTiled(_data->_headers[i].type())) + _data->_headers[i].sanityCheck(true, multipart); + else + _data->_headers[i].sanityCheck(false, multipart); + } + + // + // Check name uniqueness. + // + + if (multipart) + { + set names; + for (size_t i = 0; i < _data->_headers.size(); i++) + { + + if (names.find(_data->_headers[i].name()) != names.end()) + { + throw IEX_NAMESPACE::InputExc ("Header name " + _data->_headers[i].name() + + " is not a unique name."); + } + names.insert(_data->_headers[i].name()); + } + } + + // + // Check shared attributes compliance. + // + + if (multipart && strictSharedAttribute) + { + for (size_t i = 1; i < _data->_headers.size(); i++) + { + vector attrs; + if (_data->checkSharedAttributesValues (_data->_headers[0], _data->_headers[i], attrs)) + { + string attrNames; + for (size_t j=0; j_headers[i].name() + + " has non-conforming shared attributes: "+ + attrNames); + } + } + } + + // + // Create InputParts and read chunk offset tables. + // + + for (size_t i = 0; i < _data->_headers.size(); i++) + _data->parts.push_back( + new InputPartData(_data, _data->_headers[i], i, _data->numThreads, _data->version)); + + _data->readChunkOffsetTables(_data->reconstructChunkOffsetTable); +} + +TileOffsets* +MultiPartInputFile::Data::createTileOffsets(const Header& header) +{ + // + // Get the dataWindow information + // + + const Box2i &dataWindow = header.dataWindow(); + int minX = dataWindow.min.x; + int maxX = dataWindow.max.x; + int minY = dataWindow.min.y; + int maxY = dataWindow.max.y; + + // + // Precompute level and tile information + // + + int* numXTiles; + int* numYTiles; + int numXLevels, numYLevels; + TileDescription tileDesc = header.tileDescription(); + precalculateTileInfo (tileDesc, + minX, maxX, + minY, maxY, + numXTiles, numYTiles, + numXLevels, numYLevels); + + TileOffsets* tileOffsets = new TileOffsets (tileDesc.mode, + numXLevels, + numYLevels, + numXTiles, + numYTiles); + delete [] numXTiles; + delete [] numYTiles; + + return tileOffsets; +} + + +void +MultiPartInputFile::Data::chunkOffsetReconstruction(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is, const vector& parts) +{ + // + // Reconstruct broken chunk offset tables. Stop once we received any exception. + // + + Int64 position = is.tellg(); + + + // + // check we understand all the parts available: if not, we cannot continue + // exceptions thrown here should trickle back up to the constructor + // + + for (size_t i = 0; i < parts.size(); i++) + { + Header& header=parts[i]->header; + + // + // do we have a valid type entry? + // we only need them for true multipart files or single part non-image (deep) files + // + if(!header.hasType() && (isMultiPart(version) || isNonImage(version))) + { + throw IEX_NAMESPACE::ArgExc("cannot reconstruct incomplete file: part with missing type"); + } + if(!isSupportedType(header.type())) + { + throw IEX_NAMESPACE::ArgExc("cannot reconstruct incomplete file: part with unknown type "+header.type()); + } + } + + + // how many chunks should we read? We should stop when we reach the end + size_t total_chunks = 0; + + // for tiled-based parts, array of (pointers to) tileOffsets objects + // to create mapping between tile coordinates and chunk table indices + + + vector tileOffsets(parts.size()); + + // for scanline-based parts, number of scanlines in each part + vector rowsizes(parts.size()); + + for(size_t i = 0 ; i < parts.size() ; i++) + { + total_chunks += parts[i]->chunkOffsets.size(); + if (isTiled(parts[i]->header.type())) + { + tileOffsets[i] = createTileOffsets(parts[i]->header); + }else{ + tileOffsets[i] = NULL; + // (TODO) fix this so that it doesn't need to be revised for future compression types. + switch(parts[i]->header.compression()) + { + case DWAB_COMPRESSION : + rowsizes[i] = 256; + break; + case PIZ_COMPRESSION : + case B44_COMPRESSION : + case B44A_COMPRESSION : + case DWAA_COMPRESSION : + rowsizes[i]=32; + break; + case ZIP_COMPRESSION : + case PXR24_COMPRESSION : + rowsizes[i]=16; + break; + case ZIPS_COMPRESSION : + case RLE_COMPRESSION : + case NO_COMPRESSION : + rowsizes[i]=1; + break; + default : + throw(IEX_NAMESPACE::ArgExc("Unknown compression method in chunk offset reconstruction")); + } + } + } + + try + { + + // + // + // + + Int64 chunk_start = position; + for (size_t i = 0; i < total_chunks ; i++) + { + // + // do we have a part number? + // + + int partNumber = 0; + if(isMultiPart(version)) + { + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, partNumber); + } + + + + if(partNumber<0 || partNumber>int(parts.size())) + { + // bail here - bad part number + throw int(); + } + + Header& header = parts[partNumber]->header; + + // size of chunk NOT including multipart field + + Int64 size_of_chunk=0; + + if (isTiled(header.type())) + { + // + // + // + int tilex,tiley,levelx,levely; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, tilex); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, tiley); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, levelx); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, levely); + + //std::cout << "chunk_start for " << tilex <<',' << tiley << ',' << levelx << ' ' << levely << ':' << chunk_start << std::endl; + + + if(!tileOffsets[partNumber]) + { + // this shouldn't actually happen - we should have allocated a valid + // tileOffsets for any part which isTiled + throw int(); + + } + + if(!tileOffsets[partNumber]->isValidTile(tilex,tiley,levelx,levely)) + { + //std::cout << "invalid tile : aborting\n"; + throw int(); + } + + (*tileOffsets[partNumber])(tilex,tiley,levelx,levely)=chunk_start; + + // compute chunk sizes - different procedure for deep tiles and regular + // ones + if(header.type()==DEEPTILE) + { + Int64 packed_offset; + Int64 packed_sample; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_offset); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_sample); + + //add 40 byte header to packed sizes (tile coordinates, packed sizes, unpacked size) + size_of_chunk=packed_offset+packed_sample+40; + } + else + { + + // regular image has 20 bytes of header, 4 byte chunksize; + int chunksize; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, chunksize); + size_of_chunk=chunksize+20; + } + } + else + { + int y_coordinate; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, y_coordinate); + + y_coordinate -= header.dataWindow().min.y; + y_coordinate /= rowsizes[partNumber]; + + if(y_coordinate < 0 || y_coordinate >= int(parts[partNumber]->chunkOffsets.size())) + { + //std::cout << "aborting reconstruction: bad data " << y_coordinate << endl; + //bail to exception catcher: broken scanline + throw int(); + } + + parts[partNumber]->chunkOffsets[y_coordinate]=chunk_start; + //std::cout << "chunk_start for " << y_coordinate << ':' << chunk_start << std::endl; + + if(header.type()==DEEPSCANLINE) + { + Int64 packed_offset; + Int64 packed_sample; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_offset); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_sample); + + + size_of_chunk=packed_offset+packed_sample+28; + } + else + { + int chunksize; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, chunksize); + size_of_chunk=chunksize+8; + } + + } + + if(isMultiPart(version)) + { + chunk_start+=4; + } + + chunk_start+=size_of_chunk; + + //std::cout << " next chunk +"<header,false); + parts[i]->chunkOffsets.resize(chunkOffsetTableSize); + + for (int j = 0; j < chunkOffsetTableSize; j++) + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*is, parts[i]->chunkOffsets[j]); + + // + // Check chunk offsets, reconstruct if broken. + // At first we assume the table is complete. + // + parts[i]->completed = true; + for (int j = 0; j < chunkOffsetTableSize; j++) + { + if (parts[i]->chunkOffsets[j] <= 0) + { + brokenPartsExist = true; + parts[i]->completed = false; + break; + } + } + } + + if (brokenPartsExist && reconstructChunkOffsetTable) + chunkOffsetReconstruction(*is, parts); +} + +int +MultiPartInputFile::version() const +{ + return _data->version; +} + +bool +MultiPartInputFile::partComplete(int part) const +{ + return _data->parts[part]->completed; +} + +int +MultiPartInputFile::parts() const +{ + return int(_data->_headers.size()); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfMultiPartInputFile.h b/3rdparty/openexr/IlmImf/ImfMultiPartInputFile.h new file mode 100644 index 0000000000..67ac5a433f --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfMultiPartInputFile.h @@ -0,0 +1,134 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFMULTIPARTINPUTFILE_H_ +#define IMFMULTIPARTINPUTFILE_H_ + +#include "ImfGenericInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfThreading.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +class MultiPartInputFile : public GenericInputFile +{ + public: + IMF_EXPORT + MultiPartInputFile(const char fileName[], + int numThreads = globalThreadCount(), + bool reconstructChunkOffsetTable = true); + + IMF_EXPORT + MultiPartInputFile(IStream& is, + int numThreads = globalThreadCount(), + bool reconstructChunkOffsetTable = true); + + IMF_EXPORT + virtual ~MultiPartInputFile(); + + // ---------------------- + // Count of number of parts in file + // --------------------- + IMF_EXPORT + int parts() const; + + + //---------------------- + // Access to the headers + //---------------------- + + IMF_EXPORT + const Header & header(int n) const; + + + //---------------------------------- + // Access to the file format version + //---------------------------------- + + IMF_EXPORT + int version () const; + + + // =---------------------------------------- + // Check whether the entire chunk offset + // table for the part is written correctly + // ----------------------------------------- + IMF_EXPORT + bool partComplete(int part) const; + + + struct Data; + + + private: + Data* _data; + + MultiPartInputFile(const MultiPartInputFile &); // not implemented + + + // + // used internally by 'Part' types to access individual parts of the multipart file + // + template T* getInputPart(int partNumber); + InputPartData* getPart(int); + + void initialize(); + + + + + friend class InputPart; + friend class ScanLineInputPart; + friend class TiledInputPart; + friend class DeepScanLineInputPart; + friend class DeepTiledInputPart; + + // + // For backward compatibility. + // + + friend class InputFile; + friend class TiledInputFile; + friend class ScanLineInputFile; + friend class DeepScanLineInputFile; + friend class DeepTiledInputFile; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFMULTIPARTINPUTFILE_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfMultiPartOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfMultiPartOutputFile.cpp new file mode 100644 index 0000000000..8260cd223a --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfMultiPartOutputFile.cpp @@ -0,0 +1,519 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfMultiPartOutputFile.h" +#include "ImfBoxAttribute.h" +#include "ImfFloatAttribute.h" +#include "ImfTimeCodeAttribute.h" +#include "ImfChromaticitiesAttribute.h" +#include "ImfOutputPartData.h" +#include "ImfPartType.h" +#include "ImfOutputFile.h" +#include "ImfTiledOutputFile.h" +#include "ImfThreading.h" +#include "IlmThreadMutex.h" +#include "ImfMisc.h" +#include "ImfStdIO.h" +#include "ImfDeepScanLineOutputFile.h" +#include "ImfDeepTiledOutputFile.h" +#include "ImfOutputStreamMutex.h" + +#include "ImfNamespace.h" +#include + + +#include + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using IMATH_NAMESPACE::Box2i; +using ILMTHREAD_NAMESPACE::Lock; + + +using std::vector; +using std::map; +using std::set; + + +struct MultiPartOutputFile::Data: public OutputStreamMutex +{ + vector parts; // Contains data to initialize Output files. + bool deleteStream; // If we should delete the stream when destruction. + int numThreads; // The number of threads. + std::map _outputFiles; + std::vector
_headers; + + + void headerNameUniquenessCheck (const std::vector
&headers); + + void writeHeadersToFile (const std::vector
&headers); + + void writeChunkTableOffsets (std::vector &parts); + + + //------------------------------------- + // ensure that _headers is valid: called by constructors + //------------------------------------- + void do_header_sanity_checks(bool overrideSharedAttributes); + + // ------------------------------------------------ + // Given a source header, we copy over all the 'shared attributes' to + // the destination header and remove any conflicting ones. + // ------------------------------------------------ + void overrideSharedAttributesValues (const Header & src, + Header & dst); + + // ------------------------------------------------ + // Given a source header, we check the destination header for any + // attributes that are part of the shared attribute set. For attributes + // present in both we check the values. For attribute present in + // destination but absent in source we return false. + // For attributes present in src but missing from dst we return false + // and add the attribute to dst. + // We return false for all other cases. + // If we return true then we also populate the conflictingAttributes + // vector with the names of the attributes that failed the above. + // ------------------------------------------------ + bool checkSharedAttributesValues (const Header & src, + const Header & dst, + std::vector & conflictingAttributes) const; + Data (bool deleteStream, int numThreads): + OutputStreamMutex(), + deleteStream (deleteStream), + numThreads (numThreads) + { + } + + + ~Data() + { + if (deleteStream) delete os; + + for (size_t i = 0; i < parts.size(); i++) + delete parts[i]; + } +}; + +void +MultiPartOutputFile::Data::do_header_sanity_checks(bool overrideSharedAttributes) +{ + size_t parts = _headers.size(); + if (parts == 0) + throw IEX_NAMESPACE::ArgExc ("Empty header list."); + + bool isMultiPart = (parts > 1); + + // + // Do part 0 checks first. + // + + _headers[0].sanityCheck (_headers[0].hasTileDescription(), isMultiPart); + + + if (isMultiPart) + { + // multipart files must contain a chunkCount attribute + _headers[0].setChunkCount(getChunkOffsetTableSize(_headers[0],true)); + + for (size_t i = 1; i < parts; i++) + { + if (_headers[i].hasType() == false) + throw IEX_NAMESPACE::ArgExc ("Every header in a multipart file should have a type"); + + + _headers[i].setChunkCount(getChunkOffsetTableSize(_headers[i],true)); + _headers[i].sanityCheck (_headers[i].hasTileDescription(), isMultiPart); + + + if (overrideSharedAttributes) + overrideSharedAttributesValues(_headers[0],_headers[i]); + else + { + std::vector conflictingAttributes; + bool valid =checkSharedAttributesValues (_headers[0], + _headers[i], + conflictingAttributes); + if (valid) + { + string excMsg("Conflicting attributes found for header :: "); + excMsg += _headers[i].name(); + for (size_t i=0; i_headers.resize(parts); + + for(int i=0;i_headers[i]=headers[i]; + } + try + { + + _data->do_header_sanity_checks(overrideSharedAttributes); + + // + // Build parts and write headers and offset tables to file. + // + + _data->os = new StdOFStream (fileName); + for (size_t i = 0; i < _data->_headers.size(); i++) + _data->parts.push_back( new OutputPartData(_data, _data->_headers[i], i, numThreads, parts>1 ) ); + + writeMagicNumberAndVersionField(*_data->os, &_data->_headers[0],_data->_headers.size()); + _data->writeHeadersToFile(_data->_headers); + _data->writeChunkTableOffsets(_data->parts); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + delete _data; + + REPLACE_EXC (e, "Cannot open image file " + "\"" << fileName << "\". " << e.what()); + throw; + } + catch (...) + { + delete _data; + throw; + } +} + +MultiPartOutputFile::MultiPartOutputFile(OStream& os, + const Header* headers, + int parts, + bool overrideSharedAttributes, + int numThreads): + _data(new Data(false,numThreads)) +{ + // grab headers + _data->_headers.resize(parts); + _data->os=&os; + + for(int i=0;i_headers[i]=headers[i]; + } + try + { + + _data->do_header_sanity_checks(overrideSharedAttributes); + + // + // Build parts and write headers and offset tables to file. + // + + for (size_t i = 0; i < _data->_headers.size(); i++) + _data->parts.push_back( new OutputPartData(_data, _data->_headers[i], i, numThreads, parts>1 ) ); + + writeMagicNumberAndVersionField(*_data->os, &_data->_headers[0],_data->_headers.size()); + _data->writeHeadersToFile(_data->_headers); + _data->writeChunkTableOffsets(_data->parts); + } + catch (IEX_NAMESPACE::BaseExc &e) + { + delete _data; + + REPLACE_EXC (e, "Cannot open image stream " + "\"" << os.fileName() << "\". " << e.what()); + throw; + } + catch (...) + { + delete _data; + throw; + } +} + + +const Header & +MultiPartOutputFile::header(int n) const +{ + if(n<0 || n>int(_data->_headers.size())) + { + throw IEX_NAMESPACE::ArgExc("MultiPartOutputFile::header called with invalid part number"); + } + return _data->_headers[n]; +} + +int +MultiPartOutputFile::parts() const +{ + return _data->_headers.size(); +} + + +MultiPartOutputFile::~MultiPartOutputFile () +{ + for (map::iterator it = _data->_outputFiles.begin(); + it != _data->_outputFiles.end(); it++) + { + delete it->second; + } + + delete _data; +} + +template +T* +MultiPartOutputFile::getOutputPart(int partNumber) +{ + Lock lock(*_data); + if (_data->_outputFiles.find(partNumber) == _data->_outputFiles.end()) + { + T* file = new T(_data->parts[partNumber]); + _data->_outputFiles.insert(std::make_pair(partNumber, (GenericOutputFile*) file)); + return file; + } + else return (T*) _data->_outputFiles[partNumber]; +} + +// instance above function for all four types +template OutputFile* MultiPartOutputFile::getOutputPart(int); +template TiledOutputFile * MultiPartOutputFile::getOutputPart(int); +template DeepScanLineOutputFile * MultiPartOutputFile::getOutputPart (int); +template DeepTiledOutputFile * MultiPartOutputFile::getOutputPart (int); + + + +void +MultiPartOutputFile::Data::overrideSharedAttributesValues(const Header & src, Header & dst) +{ + // + // Display Window + // + const Box2iAttribute * displayWindow = + src.findTypedAttribute ("displayWindow"); + + if (displayWindow) + dst.insert ("displayWindow", *displayWindow); + else + dst.erase ("displayWindow"); + + + // + // Pixel Aspect Ratio + // + const FloatAttribute * pixelAspectRatio = + src.findTypedAttribute ("pixelAspectRatio"); + + if (pixelAspectRatio) + dst.insert ("pixelAspectRatio", *pixelAspectRatio); + else + dst.erase ("pixelAspectRatio"); + + + // + // Timecode + // + const TimeCodeAttribute * timeCode = + src.findTypedAttribute ("timecode"); + + if (timeCode) + dst.insert ("timecode", *timeCode); + else + dst.erase ("timecode"); + + + // + // Chromaticities + // + const ChromaticitiesAttribute * chromaticities = + src.findTypedAttribute ("chromaticities"); + + if (chromaticities) + dst.insert ("chromaticities", *chromaticities); + else + dst.erase ("chromaticities"); + +} + + +bool +MultiPartOutputFile::Data::checkSharedAttributesValues(const Header & src, + const Header & dst, + vector & conflictingAttributes) const +{ + bool conflict = false; + + // + // Display Window + // + if (src.displayWindow() != dst.displayWindow()) + { + conflict = true; + conflictingAttributes.push_back ("displayWindow"); + } + + + // + // Pixel Aspect Ratio + // + if (src.pixelAspectRatio() != dst.pixelAspectRatio()) + { + conflict = true; + conflictingAttributes.push_back ("pixelAspectRatio"); + } + + + // + // Timecode + // + const TimeCodeAttribute * srcTimeCode = src.findTypedAttribute< + TimeCodeAttribute> (TimeCodeAttribute::staticTypeName()); + const TimeCodeAttribute * dstTimeCode = dst.findTypedAttribute< + TimeCodeAttribute> (TimeCodeAttribute::staticTypeName()); + + if (dstTimeCode) + { + if ((srcTimeCode && (srcTimeCode->value() != dstTimeCode->value())) || + (!srcTimeCode)) + { + conflict = true; + conflictingAttributes.push_back (TimeCodeAttribute::staticTypeName()); + } + } + + // + // Chromaticities + // + const ChromaticitiesAttribute * srcChrom = src.findTypedAttribute< + ChromaticitiesAttribute> (ChromaticitiesAttribute::staticTypeName()); + const ChromaticitiesAttribute * dstChrom = dst.findTypedAttribute< + ChromaticitiesAttribute> (ChromaticitiesAttribute::staticTypeName()); + + if (dstChrom) + { + if ( (srcChrom && (srcChrom->value() != dstChrom->value())) || + (!srcChrom)) + { + conflict = true; + conflictingAttributes.push_back (ChromaticitiesAttribute::staticTypeName()); + } + } + + return conflict; +} + + +void +MultiPartOutputFile::Data::headerNameUniquenessCheck (const vector
&headers) +{ + set names; + for (size_t i = 0; i < headers.size(); i++) + { + if (names.find(headers[i].name()) != names.end()) + throw IEX_NAMESPACE::ArgExc ("Each part should have a unique name."); + names.insert(headers[i].name()); + } +} + +void +MultiPartOutputFile::Data::writeHeadersToFile (const vector
&headers) +{ + for (size_t i = 0; i < headers.size(); i++) + { + + // (TODO) consider deep files' preview images here. + if (headers[i].type() == TILEDIMAGE) + parts[i]->previewPosition = headers[i].writeTo(*os, true); + else + parts[i]->previewPosition = headers[i].writeTo(*os, false); + } + + // + // If a multipart file, write zero-length attribute name to mark the end of all headers. + // + + if (headers.size() !=1) + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*os, ""); +} + +void +MultiPartOutputFile::Data::writeChunkTableOffsets (vector &parts) +{ + for (size_t i = 0; i < parts.size(); i++) + { + int chunkTableSize = getChunkOffsetTableSize(parts[i]->header,false); + + Int64 pos = os->tellp(); + + if (pos == -1) + IEX_NAMESPACE::throwErrnoExc ("Cannot determine current file position (%T)."); + + parts[i]->chunkOffsetTablePosition = os->tellp(); + + // + // Fill in empty data for now. We'll write actual offsets during destruction. + // + + for (int j = 0; j < chunkTableSize; j++) + { + Int64 empty = 0; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*os, empty); + } + } +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfMultiPartOutputFile.h b/3rdparty/openexr/IlmImf/ImfMultiPartOutputFile.h new file mode 100644 index 0000000000..f8269f12aa --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfMultiPartOutputFile.h @@ -0,0 +1,122 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// Portions (c) 2012 Weta Digital Ltd +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef MULTIPARTOUTPUTFILE_H_ +#define MULTIPARTOUTPUTFILE_H_ + +#include "ImfHeader.h" +#include "ImfGenericOutputFile.h" +#include "ImfForward.h" +#include "ImfThreading.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +// +// Class responsible for handling the writing of multipart images. +// +// Note: Certain attributes are 'common' to all parts. Notably: +// * Display Window +// * Pixel Aspect Ratio +// * Time Code +// * Chromaticities +// The first header forms the basis for the set of attributes that are shared +// across the constituent parts. +// +// Parameters +// headers - pointer to array of headers; one for each part of the image file +// parts - count of number of parts +// overrideSharedAttributes - toggle for the handling of shared attributes. +// set false to check for inconsistencies, true +// to copy the values over from the first header. +// numThreads - number of threads that should be used in encoding the data. +// + +class MultiPartOutputFile : public GenericOutputFile +{ + public: + IMF_EXPORT + MultiPartOutputFile(const char fileName[], + const Header * headers, + int parts, + bool overrideSharedAttributes = false, + int numThreads = globalThreadCount()); + + IMF_EXPORT + MultiPartOutputFile(OStream & os, + const Header * headers, + int parts, + bool overrideSharedAttributes = false, + int numThreads = globalThreadCount()); + + // + // return number of parts in file + // + IMF_EXPORT + int parts() const; + + // + // return header for part n + // (note: may have additional attributes compared to that passed to constructor) + // + IMF_EXPORT + const Header & header(int n) const; + + IMF_EXPORT + ~MultiPartOutputFile(); + + struct Data; + + private: + Data* _data; + + MultiPartOutputFile(const MultiPartOutputFile &); // not implemented + + template T* getOutputPart(int partNumber); + + + friend class OutputPart; + friend class TiledOutputPart; + friend class DeepScanLineOutputPart; + friend class DeepTiledOutputPart; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* MULTIPARTOUTPUTFILE_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfMultiView.cpp b/3rdparty/openexr/IlmImf/ImfMultiView.cpp index 23879b7bd1..acca3fe4b1 100644 --- a/3rdparty/openexr/IlmImf/ImfMultiView.cpp +++ b/3rdparty/openexr/IlmImf/ImfMultiView.cpp @@ -1,9 +1,9 @@ /////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007, Weta Digital Ltd -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -15,8 +15,8 @@ // distribution. // * Neither the name of Weta Digital nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,8 +41,10 @@ #include using namespace std; +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { namespace { StringVector @@ -56,35 +58,35 @@ parseString (string name, char c = '.') StringVector r; while (name.size() > 0) - { - size_t s = name.find (c); - string sec = name.substr (0, s); + { + size_t s = name.find (c); + string sec = name.substr (0, s); - // - // Strip spaces from beginning - // + // + // Strip spaces from beginning + // - while (sec.size() > 0 && sec[0] == ' ') - sec.erase (0, 1); + while (sec.size() > 0 && sec[0] == ' ') + sec.erase (0, 1); - // - // Strip spaces from end - // + // + // Strip spaces from end + // - while (sec.size() > 0 && sec[sec.size() - 1] == ' ') - sec.erase (sec.size() - 1); + while (sec.size() > 0 && sec[sec.size() - 1] == ' ') + sec.erase (sec.size() - 1); - r.push_back (sec); + r.push_back (sec); - // - // Strip off name including ending 'c' - // + // + // Strip off name including ending 'c' + // - if (s == name.npos) - name = ""; - else - name = name.substr (s + 1); - } + if (s == name.npos) + name = ""; + else + name = name.substr (s + 1); + } return r; } @@ -101,10 +103,10 @@ viewNum (const string &view, const StringVector &multiView) // otherwise, it's some other (valid) view // - for (int i = 0; i < multiView.size(); ++i) + for (size_t i = 0; i < multiView.size(); ++i) { - if (multiView[i] == view) - return i; + if (multiView[i] == view) + return i; } return -1; @@ -117,15 +119,15 @@ string defaultViewName (const StringVector &multiView) { if (multiView.size() > 0) - return multiView[0]; + return multiView[0]; else - return ""; + return ""; } string viewFromChannelName (const string &channel, - const StringVector &multiView) + const StringVector &multiView) { // // Given the name of a channel, return the name of the view to @@ -139,41 +141,41 @@ viewFromChannelName (const string &channel, StringVector s = parseString (channel, '.'); if (s.size() == 0) - return ""; // nothing in, nothing out + return ""; // nothing in, nothing out if (s.size() == 1) { - // - // Return default view name. - // The rules say ALL channels with no periods - // in the name belong to the default view. - // + // + // Return default view name. + // The rules say ALL channels with no periods + // in the name belong to the default view. + // - return multiView[0]; + return multiView[0]; } else - { - // - // size >= 2 - the last part is the channel name, - // the next-to-last part is the view name. - // Check if that part of the name really is - // a valid view and, if it is, return it. - // - - const string &viewName = s[s.size() - 2]; - - if (viewNum (viewName, multiView) >= 0) - return viewName; - else - return ""; // not associated with any particular view + { + // + // size >= 2 - the last part is the channel name, + // the next-to-last part is the view name. + // Check if that part of the name really is + // a valid view and, if it is, return it. + // + + const string &viewName = s[s.size() - 2]; + + if (viewNum (viewName, multiView) >= 0) + return viewName; + else + return ""; // not associated with any particular view } } ChannelList channelsInView (const string & viewName, - const ChannelList & channelList, - const StringVector & multiView) + const ChannelList & channelList, + const StringVector & multiView) { // // Return a list of all channels belonging to view viewName. @@ -182,22 +184,22 @@ channelsInView (const string & viewName, ChannelList q; for (ChannelList::ConstIterator i = channelList.begin(); - i != channelList.end(); - ++i) + i != channelList.end(); + ++i) { - // - // Get view name for this channel - // + // + // Get view name for this channel + // - string view = viewFromChannelName (i.name(), multiView); + string view = viewFromChannelName (i.name(), multiView); - // - // Insert channel into q if it's a member of view viewName - // + // + // Insert channel into q if it's a member of view viewName + // - if (view == viewName) - q.insert (i.name(), i.channel()); + if (view == viewName) + q.insert (i.name(), i.channel()); } return q; @@ -206,21 +208,21 @@ channelsInView (const string & viewName, ChannelList channelsInNoView (const ChannelList &channelList, - const StringVector &multiView) + const StringVector &multiView) { // // Return a list of channels not associated with any named view. // - return channelsInView ("", channelList, multiView); + return channelsInView ("", channelList, multiView); } bool -areCounterparts (const string &channel1, - const string &channel2, - const StringVector &multiView) +areCounterparts (const string &channel1, + const string &channel2, + const StringVector &multiView) { // // Given two channels, return true if they are the same @@ -228,55 +230,55 @@ areCounterparts (const string &channel1, // StringVector chan1 = parseString (channel1); - unsigned int size1 = chan1.size(); // number of SECTIONS in string - // name (not string length) + size_t size1 = chan1.size(); // number of SECTIONS in string + // name (not string length) StringVector chan2 = parseString (channel2); - unsigned int size2 = chan2.size(); + size_t size2 = chan2.size(); if (size1 == 0 || size2 == 0) - return false; - + return false; + // // channel1 and channel2 can't be counterparts // if either channel is in no view. // if (size1 > 1 && viewNum (chan1[size1 - 2], multiView) == -1) - return false; + return false; if (size2 > 1 && viewNum (chan2[size2 - 2], multiView) == -1) - return false; + return false; if (viewFromChannelName (channel1, multiView) == - viewFromChannelName (channel2, multiView)) + viewFromChannelName (channel2, multiView)) { - // - // channel1 and channel2 are not counterparts - // if they are in the same view. - // + // + // channel1 and channel2 are not counterparts + // if they are in the same view. + // - return false; + return false; } if (size1 == 1) - { - // - // channel1 is a default channel - the channels will only be - // counterparts if channel2 is of the form . - // + { + // + // channel1 is a default channel - the channels will only be + // counterparts if channel2 is of the form . + // - return size2 == 2 && chan1[0] == chan2[1]; + return size2 == 2 && chan1[0] == chan2[1]; } if (size2 == 1) { - // - // channel2 is a default channel - the channels will only be - // counterparts if channel1 is of the form . - // + // + // channel2 is a default channel - the channels will only be + // counterparts if channel1 is of the form . + // - return size1 == 2 && chan2[0] == chan1[1]; + return size1 == 2 && chan2[0] == chan1[1]; } // @@ -286,12 +288,12 @@ areCounterparts (const string &channel1, // if (size1 != size2) - return false; + return false; - for(int i = 0; i < size1; ++i) + for(size_t i = 0; i < size1; ++i) { - if (i != size1 - 2 && chan1[i] != chan2[i]) - return false; + if (i != size1 - 2 && chan1[i] != chan2[i]) + return false; } return true; @@ -300,8 +302,8 @@ areCounterparts (const string &channel1, ChannelList channelInAllViews (const string &channelName, - const ChannelList &channelList, - const StringVector &multiView) + const ChannelList &channelList, + const StringVector &multiView) { // // Given the name of a channel, return a @@ -311,14 +313,14 @@ channelInAllViews (const string &channelName, ChannelList q; for (ChannelList::ConstIterator i=channelList.begin(); - i != channelList.end(); - ++i) + i != channelList.end(); + ++i) { - if (i.name() == channelName || - areCounterparts (i.name(), channelName, multiView)) - { - q.insert (i.name(), i.channel()); - } + if (i.name() == channelName || + areCounterparts (i.name(), channelName, multiView)) + { + q.insert (i.name(), i.channel()); + } } return q; @@ -327,9 +329,9 @@ channelInAllViews (const string &channelName, string channelInOtherView (const string &channelName, - const ChannelList &channelList, - const StringVector &multiView, - const string &otherViewName) + const ChannelList &channelList, + const StringVector &multiView, + const string &otherViewName) { // // Given the name of a channel in one view, return the @@ -337,14 +339,14 @@ channelInOtherView (const string &channelName, // for (ChannelList::ConstIterator i=channelList.begin(); - i != channelList.end(); - ++i) + i != channelList.end(); + ++i) { - if (viewFromChannelName (i.name(), multiView) == otherViewName && - areCounterparts (i.name(), channelName, multiView)) - { - return i.name(); - } + if (viewFromChannelName (i.name(), multiView) == otherViewName && + areCounterparts (i.name(), channelName, multiView)) + { + return i.name(); + } } return ""; @@ -353,8 +355,8 @@ channelInOtherView (const string &channelName, string insertViewName (const string &channel, - const StringVector &multiView, - int i) + const StringVector &multiView, + int i) { // // Insert multiView[i] into the channel name if appropriate. @@ -363,16 +365,16 @@ insertViewName (const string &channel, StringVector s = parseString (channel, '.'); if (s.size() == 0) - return ""; // nothing in, nothing out + return ""; // nothing in, nothing out if (s.size() == 1 && i == 0) { - // - // Channel in the default view, with no periods in its name. - // Do not insert view name. - // + // + // Channel in the default view, with no periods in its name. + // Do not insert view name. + // - return channel; + return channel; } // @@ -381,16 +383,53 @@ insertViewName (const string &channel, string newName; - for (int j = 0; j < s.size(); ++j) + for (size_t j = 0; j < s.size(); ++j) { - if (j < s.size() - 1) - newName += s[j] + "."; - else - newName += multiView[i] + "." + s[j]; + if (j < s.size() - 1) + newName += s[j] + "."; + else + newName += multiView[i] + "." + s[j]; } return newName; } -} // namespace Imf +string +removeViewName(const string & channel,const string & view) +{ + StringVector s = parseString (channel, '.'); + + if (s.size() == 0) + return ""; // nothing in, nothing out + + if (s.size() == 1) + { + // + // Channel in the default view, since no periods in its name. + // No viewname to remove + // + + return channel; + } + + string newName; + for( size_t j = 0 ; j < s.size() ; ++j) + { + // only add the penultimate string part + // if it doesn't match the view name + if(j+2!=s.size() || s[j]!=view) + { + newName += s[j]; + if(j+1!=s.size()) + { + newName += "."; + } + } + } + + return newName; + +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfMultiView.h b/3rdparty/openexr/IlmImf/ImfMultiView.h index f4df4b303e..127f97d858 100644 --- a/3rdparty/openexr/IlmImf/ImfMultiView.h +++ b/3rdparty/openexr/IlmImf/ImfMultiView.h @@ -1,9 +1,9 @@ /////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007, Weta Digital Ltd -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -15,8 +15,8 @@ // distribution. // * Neither the name of Weta Digital nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -35,8 +35,10 @@ #ifndef INCLUDED_IMF_MULTIVIEW_H #define INCLUDED_IMF_MULTIVIEW_H -#include -#include +#include "ImfChannelList.h" +#include "ImfStringVectorAttribute.h" +#include "ImfExport.h" +#include "ImfNamespace.h" //----------------------------------------------------------------------------- // @@ -80,7 +82,7 @@ // //----------------------------------------------------------------------------- -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER // // Return the name of the default view given a multi-view string vector, @@ -88,6 +90,7 @@ namespace Imf { // vector is empty, return "". // +IMF_EXPORT std::string defaultViewName (const StringVector &multiView); @@ -97,6 +100,7 @@ std::string defaultViewName (const StringVector &multiView); // is not a member of any named view. // +IMF_EXPORT std::string viewFromChannelName (const std::string &channel, const StringVector &multiView); @@ -107,6 +111,7 @@ std::string viewFromChannelName (const std::string &channel, // belongs to no view or if both channels belong to the same view.) // +IMF_EXPORT bool areCounterparts (const std::string &channel1, const std::string &channel2, const StringVector &multiView); @@ -115,6 +120,7 @@ bool areCounterparts (const std::string &channel1, // Return a list of all channels belonging to view viewName. // +IMF_EXPORT ChannelList channelsInView (const std::string &viewName, const ChannelList &channelList, const StringVector &multiView); @@ -123,6 +129,7 @@ ChannelList channelsInView (const std::string &viewName, // Return a list of channels not associated with any view. // +IMF_EXPORT ChannelList channelsInNoView (const ChannelList &channelList, const StringVector &multiView); @@ -132,6 +139,7 @@ ChannelList channelsInNoView (const ChannelList &channelList, // X.right.Y, X.centre.Y, etc.). // +IMF_EXPORT ChannelList channelInAllViews (const std::string &channame, const ChannelList &channelList, const StringVector &multiView); @@ -143,6 +151,7 @@ ChannelList channelInAllViews (const std::string &channame, // exist. // +IMF_EXPORT std::string channelInOtherView (const std::string &channel, const ChannelList &channelList, const StringVector &multiView, @@ -155,10 +164,24 @@ std::string channelInOtherView (const std::string &channel, // not insert the view name. // +IMF_EXPORT std::string insertViewName (const std::string &channel, - const StringVector &multiView, - int i); + const StringVector &multiView, + int i); + +// +// Given a channel name that does may include a view name, return +// string without the view name. If the string does not contain +// the view name, return the string unaltered. +// (Will only remove the viewname if it is in the correct position +// in the string) +// + +IMF_EXPORT +std::string removeViewName (const std::string &channel, + const std::string &view); + -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfName.h b/3rdparty/openexr/IlmImf/ImfName.h index f443ee7b44..17fa33a3f9 100644 --- a/3rdparty/openexr/IlmImf/ImfName.h +++ b/3rdparty/openexr/IlmImf/ImfName.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,8 +45,10 @@ //----------------------------------------------------------------------------- #include +#include "ImfNamespace.h" +#include "ImfExport.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class Name @@ -57,7 +59,9 @@ class Name // Constructors //------------- + IMF_EXPORT Name (); + IMF_EXPORT Name (const char text[]); @@ -65,6 +69,7 @@ class Name // Assignment operator //-------------------- + IMF_EXPORT Name & operator = (const char text[]); @@ -72,7 +77,9 @@ class Name // Access to the string //--------------------- + IMF_EXPORT const char * text () const {return _text;} + IMF_EXPORT const char * operator * () const {return _text;} //--------------- @@ -88,8 +95,11 @@ class Name }; +IMF_EXPORT bool operator == (const Name &x, const Name &y); +IMF_EXPORT bool operator != (const Name &x, const Name &y); +IMF_EXPORT bool operator < (const Name &x, const Name &y); @@ -141,6 +151,9 @@ operator < (const Name &x, const Name &y) } -} // namespace IMF +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfNamespace.h b/3rdparty/openexr/IlmImf/ImfNamespace.h new file mode 100644 index 0000000000..c36a31eec9 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfNamespace.h @@ -0,0 +1,115 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMFNAMESPACE_H +#define INCLUDED_IMFNAMESPACE_H + +// +// The purpose of this file is to have all of the Imath symbols defined within +// the OPENEXR_IMF_INTERNAL_NAMESPACE namespace rather than the standard Imath +// namespace. Those symbols are made available to client code through the +// OPENEXR_IMF_NAMESPACE in addition to the OPENEXR_IMF_INTERNAL_NAMESPACE. +// +// To ensure source code compatibility, the OPENEXR_IMF_NAMESPACE defaults to +// Imath and then "using namespace OPENEXR_IMF_INTERNAL_NAMESPACE;" brings all +// of the declarations from the OPENEXR_IMF_INTERNAL_NAMESPACE into the +// OPENEXR_IMF_NAMESPACE. +// This means that client code can continue to use syntax like +// Imf::Header, but at link time it will resolve to a +// mangled symbol based on the OPENEXR_IMF_INTERNAL_NAMESPACE. +// +// As an example, if one needed to build against a newer version of Imath and +// have it run alongside an older version in the same application, it is now +// possible to use an internal namespace to prevent collisions between the +// older versions of Imath symbols and the newer ones. To do this, the +// following could be defined at build time: +// +// OPENEXR_IMF_INTERNAL_NAMESPACE = Imf_v2 +// +// This means that declarations inside Imath headers look like this (after +// the preprocessor has done its work): +// +// namespace Imf_v2 { +// ... +// class declarations +// ... +// } +// +// namespace Imf { +// using namespace IMF_NAMESPACE_v2; +// } +// + +// +// Open Source version of this file pulls in the OpenEXRConfig.h file +// for the configure time options. +// +#include "OpenEXRConfig.h" + + +#ifndef OPENEXR_IMF_NAMESPACE +#define OPENEXR_IMF_NAMESPACE Imf +#endif + +#ifndef OPENEXR_IMF_INTERNAL_NAMESPACE +#define OPENEXR_IMF_INTERNAL_NAMESPACE OPENEXR_IMF_NAMESPACE +#endif + +// +// We need to be sure that we import the internal namespace into the public one. +// To do this, we use the small bit of code below which initially defines +// OPENEXR_IMF_INTERNAL_NAMESPACE (so it can be referenced) and then defines +// OPENEXR_IMF_NAMESPACE and pulls the internal symbols into the public +// namespace. +// + +namespace OPENEXR_IMF_INTERNAL_NAMESPACE {} +namespace OPENEXR_IMF_NAMESPACE { + using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; +} + +// +// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that +// future extension to the namespace mechanism is possible without changing +// project source code. +// + +#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER namespace OPENEXR_IMF_INTERNAL_NAMESPACE { +#define OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT } + +#define OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER namespace OPENEXR_IMF_INTERNAL_NAMESPACE { +#define OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT } + + +#endif /* INCLUDED_IMFNAMESPACE_H */ diff --git a/3rdparty/openexr/IlmImf/ImfOpaqueAttribute.cpp b/3rdparty/openexr/IlmImf/ImfOpaqueAttribute.cpp index ccb37e51a0..4a473efe27 100644 --- a/3rdparty/openexr/IlmImf/ImfOpaqueAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfOpaqueAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,8 +43,9 @@ #include #include "Iex.h" #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER OpaqueAttribute::OpaqueAttribute (const char typeName[]): @@ -79,22 +80,22 @@ OpaqueAttribute::typeName () const } -Attribute * +Attribute * OpaqueAttribute::copy () const { return new OpaqueAttribute (*this); } -void -OpaqueAttribute::writeValueTo (OStream &os, int) const +void +OpaqueAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _data, _dataSize); } -void -OpaqueAttribute::readValueFrom (IStream &is, int size, int) +void +OpaqueAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { _data.resizeErase (size); _dataSize = size; @@ -102,18 +103,18 @@ OpaqueAttribute::readValueFrom (IStream &is, int size, int) } -void +void OpaqueAttribute::copyValueFrom (const Attribute &other) { const OpaqueAttribute *oa = dynamic_cast (&other); if (oa == 0 || strcmp (_typeName, oa->_typeName)) { - THROW (Iex::TypeExc, "Cannot copy the value of an " - "image file attribute of type " - "\"" << other.typeName() << "\" " - "to an attribute of type " - "\"" << _typeName << "\"."); + THROW (IEX_NAMESPACE::TypeExc, "Cannot copy the value of an " + "image file attribute of type " + "\"" << other.typeName() << "\" " + "to an attribute of type " + "\"" << _typeName << "\"."); } _data.resizeErase (oa->_dataSize); @@ -122,4 +123,4 @@ OpaqueAttribute::copyValueFrom (const Attribute &other) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfOpaqueAttribute.h b/3rdparty/openexr/IlmImf/ImfOpaqueAttribute.h index b8593b020d..9340ee9fb9 100644 --- a/3rdparty/openexr/IlmImf/ImfOpaqueAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfOpaqueAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -49,10 +49,11 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfArray.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class OpaqueAttribute: public Attribute @@ -63,8 +64,11 @@ class OpaqueAttribute: public Attribute // Constructors and destructor //---------------------------- + IMF_EXPORT OpaqueAttribute (const char typeName[]); + IMF_EXPORT OpaqueAttribute (const OpaqueAttribute &other); + IMF_EXPORT virtual ~OpaqueAttribute (); @@ -72,13 +76,15 @@ class OpaqueAttribute: public Attribute // Get this attribute's type name //------------------------------- + IMF_EXPORT virtual const char * typeName () const; - + //------------------------------ // Make a copy of this attribute //------------------------------ + IMF_EXPORT virtual Attribute * copy () const; @@ -86,13 +92,16 @@ class OpaqueAttribute: public Attribute // I/O and copying //---------------- - virtual void writeValueTo (OStream &os, - int version) const; + IMF_EXPORT + virtual void writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + int version) const; - virtual void readValueFrom (IStream &is, - int size, - int version); + IMF_EXPORT + virtual void readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version); + IMF_EXPORT virtual void copyValueFrom (const Attribute &other); @@ -104,11 +113,6 @@ class OpaqueAttribute: public Attribute }; -} // namespace Imf - -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfOptimizedPixelReading.h b/3rdparty/openexr/IlmImf/ImfOptimizedPixelReading.h new file mode 100644 index 0000000000..d0bc857844 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfOptimizedPixelReading.h @@ -0,0 +1,646 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Autodesk, Inc. +// +// All rights reserved. +// +// Implementation of IIF-specific file format and speed optimizations +// provided by Innobec Technologies inc on behalf of Autodesk. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#pragma once + +#ifndef INCLUDED_IMF_OPTIMIZED_PIXEL_READING_H +#define INCLUDED_IMF_OPTIMIZED_PIXEL_READING_H + +#include "ImfSimd.h" +#include "ImfSystemSpecific.h" +#include +#include "ImfChannelList.h" +#include "ImfFrameBuffer.h" +#include "ImfStringVectorAttribute.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +class OptimizationMode +{ +public: + + + bool _optimizable; + int _ySampling; + OptimizationMode() : _optimizable(false) {} + +}; + + +#ifdef IMF_HAVE_SSE2 + + +//------------------------------------------------------------------------ +// Test for SSE pointer alignemnt +//------------------------------------------------------------------------ +EXR_FORCEINLINE +bool +isPointerSSEAligned (const void* EXR_RESTRICT pPointer) +{ + uintptr_t trailingBits = ((uintptr_t)pPointer) & 15; + return trailingBits == 0; +} + +//------------------------------------------------------------------------ +// Load SSE from address into register +//------------------------------------------------------------------------ +template +EXR_FORCEINLINE +__m128i loadSSE (__m128i*& loadAddress) +{ + // throw exception :: this is not accepted + return _mm_loadu_si128 (loadAddress); +} + +template<> +EXR_FORCEINLINE +__m128i loadSSE (__m128i*& loadAddress) +{ + return _mm_loadu_si128 (loadAddress); +} + +template<> +EXR_FORCEINLINE +__m128i loadSSE (__m128i*& loadAddress) +{ + return _mm_load_si128 (loadAddress); +} + +//------------------------------------------------------------------------ +// Store SSE from register into address +//------------------------------------------------------------------------ +template +EXR_FORCEINLINE +void storeSSE (__m128i*& storeAddress, __m128i& dataToStore) +{ + +} + +template<> +EXR_FORCEINLINE +void +storeSSE (__m128i*& storeAddress, __m128i& dataToStore) +{ + _mm_storeu_si128 (storeAddress, dataToStore); +} + +template<> +EXR_FORCEINLINE +void +storeSSE (__m128i*& storeAddress, __m128i& dataToStore) +{ + _mm_stream_si128 (storeAddress, dataToStore); +} + + + +//------------------------------------------------------------------------ +// +// Write to RGBA +// +//------------------------------------------------------------------------ + +// +// Using SSE intrinsics +// +template +EXR_FORCEINLINE +void writeToRGBASSETemplate + (__m128i*& readPtrSSERed, + __m128i*& readPtrSSEGreen, + __m128i*& readPtrSSEBlue, + __m128i*& readPtrSSEAlpha, + __m128i*& writePtrSSE, + const size_t& lPixelsToCopySSE) +{ + for (size_t i = 0; i < lPixelsToCopySSE; ++i) + { + __m128i redRegister = loadSSE (readPtrSSERed); + __m128i greenRegister = loadSSE (readPtrSSEGreen); + __m128i blueRegister = loadSSE (readPtrSSEBlue); + __m128i alphaRegister = loadSSE (readPtrSSEAlpha); + + __m128i redGreenRegister = _mm_unpacklo_epi16 (redRegister, + greenRegister); + __m128i blueAlphaRegister = _mm_unpacklo_epi16 (blueRegister, + alphaRegister); + + __m128i pixel12Register = _mm_unpacklo_epi32 (redGreenRegister, + blueAlphaRegister); + __m128i pixel34Register = _mm_unpackhi_epi32 (redGreenRegister, + blueAlphaRegister); + + storeSSE (writePtrSSE, pixel12Register); + ++writePtrSSE; + + storeSSE (writePtrSSE, pixel34Register); + ++writePtrSSE; + + redGreenRegister = _mm_unpackhi_epi16 (redRegister, greenRegister); + blueAlphaRegister = _mm_unpackhi_epi16 (blueRegister, alphaRegister); + + pixel12Register = _mm_unpacklo_epi32 (redGreenRegister, + blueAlphaRegister); + pixel34Register = _mm_unpackhi_epi32 (redGreenRegister, + blueAlphaRegister); + + storeSSE (writePtrSSE, pixel12Register); + ++writePtrSSE; + + storeSSE (writePtrSSE, pixel34Register); + ++writePtrSSE; + + ++readPtrSSEAlpha; + ++readPtrSSEBlue; + ++readPtrSSEGreen; + ++readPtrSSERed; + } +} + +// +// Not using SSE intrinsics. This is still faster than the alternative +// because we have multiple read pointers and therefore we are able to +// take advantage of data locality for write operations. +// +EXR_FORCEINLINE +void writeToRGBANormal (unsigned short*& readPtrRed, + unsigned short*& readPtrGreen, + unsigned short*& readPtrBlue, + unsigned short*& readPtrAlpha, + unsigned short*& writePtr, + const size_t& lPixelsToCopy) +{ + for (size_t i = 0; i < lPixelsToCopy; ++i) + { + *(writePtr++) = *(readPtrRed++); + *(writePtr++) = *(readPtrGreen++); + *(writePtr++) = *(readPtrBlue++); + *(writePtr++) = *(readPtrAlpha++); + } +} + +// +// Determine which (template) version to use by checking whether pointers +// are aligned +// +EXR_FORCEINLINE +void optimizedWriteToRGBA (unsigned short*& readPtrRed, + unsigned short*& readPtrGreen, + unsigned short*& readPtrBlue, + unsigned short*& readPtrAlpha, + unsigned short*& writePtr, + const size_t& pixelsToCopySSE, + const size_t& pixelsToCopyNormal) +{ + bool readPtrAreAligned = true; + + readPtrAreAligned &= isPointerSSEAligned(readPtrRed); + readPtrAreAligned &= isPointerSSEAligned(readPtrGreen); + readPtrAreAligned &= isPointerSSEAligned(readPtrBlue); + readPtrAreAligned &= isPointerSSEAligned(readPtrAlpha); + + bool writePtrIsAligned = isPointerSSEAligned(writePtr); + + if (!readPtrAreAligned && !writePtrIsAligned) + { + writeToRGBASSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + (__m128i*&)readPtrAlpha, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if (!readPtrAreAligned && writePtrIsAligned) + { + writeToRGBASSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + (__m128i*&)readPtrAlpha, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if (readPtrAreAligned && !writePtrIsAligned) + { + writeToRGBASSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + (__m128i*&)readPtrAlpha, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if(readPtrAreAligned && writePtrIsAligned) + { + writeToRGBASSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + (__m128i*&)readPtrAlpha, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + + writeToRGBANormal (readPtrRed, readPtrGreen, readPtrBlue, readPtrAlpha, + writePtr, pixelsToCopyNormal); +} + + + +//------------------------------------------------------------------------ +// +// Write to RGBA Fill A +// +//------------------------------------------------------------------------ + +// +// Using SSE intrinsics +// +template +EXR_FORCEINLINE +void +writeToRGBAFillASSETemplate (__m128i*& readPtrSSERed, + __m128i*& readPtrSSEGreen, + __m128i*& readPtrSSEBlue, + const unsigned short& alphaFillValue, + __m128i*& writePtrSSE, + const size_t& pixelsToCopySSE) +{ + const __m128i dummyAlphaRegister = _mm_set_epi16 (alphaFillValue, + alphaFillValue, + alphaFillValue, + alphaFillValue, + alphaFillValue, + alphaFillValue, + alphaFillValue, + alphaFillValue); + + for (size_t pixelCounter = 0; pixelCounter < pixelsToCopySSE; ++pixelCounter) + { + __m128i redRegister = loadSSE (readPtrSSERed); + __m128i greenRegister = loadSSE (readPtrSSEGreen); + __m128i blueRegister = loadSSE (readPtrSSEBlue); + + __m128i redGreenRegister = _mm_unpacklo_epi16 (redRegister, + greenRegister); + __m128i blueAlphaRegister = _mm_unpacklo_epi16 (blueRegister, + dummyAlphaRegister); + + __m128i pixel12Register = _mm_unpacklo_epi32 (redGreenRegister, + blueAlphaRegister); + __m128i pixel34Register = _mm_unpackhi_epi32 (redGreenRegister, + blueAlphaRegister); + + storeSSE (writePtrSSE, pixel12Register); + ++writePtrSSE; + + storeSSE (writePtrSSE, pixel34Register); + ++writePtrSSE; + + redGreenRegister = _mm_unpackhi_epi16 (redRegister, + greenRegister); + blueAlphaRegister = _mm_unpackhi_epi16 (blueRegister, + dummyAlphaRegister); + + pixel12Register = _mm_unpacklo_epi32 (redGreenRegister, + blueAlphaRegister); + pixel34Register = _mm_unpackhi_epi32 (redGreenRegister, + blueAlphaRegister); + + storeSSE (writePtrSSE, pixel12Register); + ++writePtrSSE; + + storeSSE (writePtrSSE, pixel34Register); + ++writePtrSSE; + + ++readPtrSSEBlue; + ++readPtrSSEGreen; + ++readPtrSSERed; + } +} + +// +// Not using SSE intrinsics. This is still faster than the alternative +// because we have multiple read pointers and therefore we are able to +// take advantage of data locality for write operations. +// +EXR_FORCEINLINE +void +writeToRGBAFillANormal (unsigned short*& readPtrRed, + unsigned short*& readPtrGreen, + unsigned short*& readPtrBlue, + const unsigned short& alphaFillValue, + unsigned short*& writePtr, + const size_t& pixelsToCopy) +{ + for (size_t i = 0; i < pixelsToCopy; ++i) + { + *(writePtr++) = *(readPtrRed++); + *(writePtr++) = *(readPtrGreen++); + *(writePtr++) = *(readPtrBlue++); + *(writePtr++) = alphaFillValue; + } +} + +// +// Determine which (template) version to use by checking whether pointers +// are aligned. +// +EXR_FORCEINLINE +void +optimizedWriteToRGBAFillA (unsigned short*& readPtrRed, + unsigned short*& readPtrGreen, + unsigned short*& readPtrBlue, + const unsigned short& alphaFillValue, + unsigned short*& writePtr, + const size_t& pixelsToCopySSE, + const size_t& pixelsToCopyNormal) +{ + bool readPtrAreAligned = true; + + readPtrAreAligned &= isPointerSSEAligned (readPtrRed); + readPtrAreAligned &= isPointerSSEAligned (readPtrGreen); + readPtrAreAligned &= isPointerSSEAligned (readPtrBlue); + + bool writePtrIsAligned = isPointerSSEAligned (writePtr); + + if (!readPtrAreAligned && !writePtrIsAligned) + { + writeToRGBAFillASSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + alphaFillValue, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if (!readPtrAreAligned && writePtrIsAligned) + { + writeToRGBAFillASSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + alphaFillValue, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if (readPtrAreAligned && !writePtrIsAligned) + { + writeToRGBAFillASSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + alphaFillValue, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if (readPtrAreAligned && writePtrIsAligned) + { + writeToRGBAFillASSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + alphaFillValue, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + + writeToRGBAFillANormal (readPtrRed, + readPtrGreen, readPtrBlue, alphaFillValue, + writePtr, pixelsToCopyNormal); +} + + + +//------------------------------------------------------------------------ +// +// Write to RGB +// +//------------------------------------------------------------------------ + +// +// Using SSE intrinsics +// +template +EXR_FORCEINLINE +void +writeToRGBSSETemplate (__m128i*& readPtrSSERed, + __m128i*& readPtrSSEGreen, + __m128i*& readPtrSSEBlue, + __m128i*& writePtrSSE, + const size_t& pixelsToCopySSE) +{ + + for (size_t pixelCounter = 0; pixelCounter < pixelsToCopySSE; ++pixelCounter) + { + // + // Need to shuffle and unpack pointers to obtain my first register + // We must save 8 pixels at a time, so we must have the following three registers at the end: + // 1) R1 G1 B1 R2 G2 B2 R3 G3 + // 2) B3 R4 G4 B4 R5 G5 B5 R6 + // 3) G6 B6 R7 G7 B7 R8 G8 B8 + // + __m128i redRegister = loadSSE (readPtrSSERed); + __m128i greenRegister = loadSSE (readPtrSSEGreen); + __m128i blueRegister = loadSSE (readPtrSSEBlue); + + // + // First register: R1 G1 B1 R2 G2 B2 R3 G3 + // Construct 2 registers and then unpack them to obtain our final result: + // + __m128i redGreenRegister = _mm_unpacklo_epi16 (redRegister, + greenRegister); + __m128i redBlueRegister = _mm_unpacklo_epi16 (redRegister, + blueRegister); + __m128i greenBlueRegister = _mm_unpacklo_epi16 (greenRegister, + blueRegister); + + // Left Part (R1 G1 B1 R2) + __m128i quarterRight = _mm_shufflelo_epi16 (redBlueRegister, + _MM_SHUFFLE(3,0,2,1)); + __m128i halfLeft = _mm_unpacklo_epi32 (redGreenRegister, + quarterRight); + + // Right Part (G2 B2 R3 G3) + __m128i quarterLeft = _mm_shuffle_epi32 (greenBlueRegister, + _MM_SHUFFLE(3,2,0,1)); + quarterRight = _mm_shuffle_epi32 (redGreenRegister, + _MM_SHUFFLE(3,0,1,2)); + __m128i halfRight = _mm_unpacklo_epi32 (quarterLeft, quarterRight); + + __m128i fullRegister = _mm_unpacklo_epi64 (halfLeft, halfRight); + storeSSE (writePtrSSE, fullRegister); + ++writePtrSSE; + + // + // Second register: B3 R4 G4 B4 R5 G5 B5 R6 + // + + // Left Part (B3, R4, G4, B4) + quarterLeft = _mm_shufflehi_epi16 (redBlueRegister, + _MM_SHUFFLE(0, 3, 2, 1)); + quarterRight = _mm_shufflehi_epi16 (greenBlueRegister, + _MM_SHUFFLE(1, 0, 3, 2)); + halfLeft = _mm_unpackhi_epi32 (quarterLeft, quarterRight); + + // Update the registers + redGreenRegister = _mm_unpackhi_epi16 (redRegister, greenRegister); + redBlueRegister = _mm_unpackhi_epi16 (redRegister, blueRegister); + greenBlueRegister = _mm_unpackhi_epi16 (greenRegister, blueRegister); + + // Right Part (R5 G5 B5 R6) + quarterRight = _mm_shufflelo_epi16 (redBlueRegister, + _MM_SHUFFLE(3,0,2,1)); + halfRight = _mm_unpacklo_epi32 (redGreenRegister, quarterRight); + + fullRegister = _mm_unpacklo_epi64 (halfLeft, halfRight); + storeSSE (writePtrSSE, fullRegister); + ++writePtrSSE; + + // + // Third register: G6 B6 R7 G7 B7 R8 G8 B8 + // + + // Left part (G6 B6 R7 G7) + quarterLeft = _mm_shuffle_epi32 (greenBlueRegister, + _MM_SHUFFLE(3,2,0,1)); + quarterRight = _mm_shuffle_epi32 (redGreenRegister, + _MM_SHUFFLE(3,0,1,2)); + halfLeft = _mm_unpacklo_epi32 (quarterLeft, quarterRight); + + // Right part (B7 R8 G8 B8) + quarterLeft = _mm_shufflehi_epi16 (redBlueRegister, + _MM_SHUFFLE(0, 3, 2, 1)); + quarterRight = _mm_shufflehi_epi16 (greenBlueRegister, + _MM_SHUFFLE(1, 0, 3, 2)); + halfRight = _mm_unpackhi_epi32 (quarterLeft, quarterRight); + + fullRegister = _mm_unpacklo_epi64 (halfLeft, halfRight); + storeSSE (writePtrSSE, fullRegister); + ++writePtrSSE; + + // + // Increment read pointers + // + ++readPtrSSEBlue; + ++readPtrSSEGreen; + ++readPtrSSERed; + } +} + +// +// Not using SSE intrinsics. This is still faster than the alternative +// because we have multiple read pointers and therefore we are able to +// take advantage of data locality for write operations. +// +EXR_FORCEINLINE +void +writeToRGBNormal (unsigned short*& readPtrRed, + unsigned short*& readPtrGreen, + unsigned short*& readPtrBlue, + unsigned short*& writePtr, + const size_t& pixelsToCopy) +{ + for (size_t i = 0; i < pixelsToCopy; ++i) + { + *(writePtr++) = *(readPtrRed++); + *(writePtr++) = *(readPtrGreen++); + *(writePtr++) = *(readPtrBlue++); + } +} + +// +// Determine which (template) version to use by checking whether pointers +// are aligned +// +EXR_FORCEINLINE +void optimizedWriteToRGB (unsigned short*& readPtrRed, + unsigned short*& readPtrGreen, + unsigned short*& readPtrBlue, + unsigned short*& writePtr, + const size_t& pixelsToCopySSE, + const size_t& pixelsToCopyNormal) +{ + bool readPtrAreAligned = true; + + readPtrAreAligned &= isPointerSSEAligned(readPtrRed); + readPtrAreAligned &= isPointerSSEAligned(readPtrGreen); + readPtrAreAligned &= isPointerSSEAligned(readPtrBlue); + + bool writePtrIsAligned = isPointerSSEAligned(writePtr); + + if (!readPtrAreAligned && !writePtrIsAligned) + { + writeToRGBSSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if (!readPtrAreAligned && writePtrIsAligned) + { + writeToRGBSSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if (readPtrAreAligned && !writePtrIsAligned) + { + writeToRGBSSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + else if (readPtrAreAligned && writePtrIsAligned) + { + writeToRGBSSETemplate ((__m128i*&)readPtrRed, + (__m128i*&)readPtrGreen, + (__m128i*&)readPtrBlue, + (__m128i*&)writePtr, + pixelsToCopySSE); + } + + + writeToRGBNormal (readPtrRed, readPtrGreen, readPtrBlue, + writePtr, pixelsToCopyNormal); +} + + + + +#else // ! defined IMF_HAVE_SSE2 + +#endif // defined IMF_HAVE_SSE2 + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfOutputFile.cpp index e69b92bd57..ff44e66648 100644 --- a/3rdparty/openexr/IlmImf/ImfOutputFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfOutputFile.cpp @@ -1,10 +1,14 @@ +// +///\todo: version needs fixing! +// + /////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +20,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -48,35 +52,41 @@ #include "ImathBox.h" #include "ImathFun.h" #include -#include +#include "ImfXdr.h" #include +#include #include "IlmThreadPool.h" +#include "ImfOutputStreamMutex.h" #include "IlmThreadSemaphore.h" #include "IlmThreadMutex.h" #include "Iex.h" +#include "ImfInputPart.h" +#include "ImfNamespace.h" +#include "ImfOutputPartData.h" + #include #include #include #include -#include // for std::max() - +#include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -using Imath::Box2i; -using Imath::divp; -using Imath::modp; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::divp; +using IMATH_NAMESPACE::modp; using std::string; using std::vector; using std::ofstream; using std::min; using std::max; -using IlmThread::Mutex; -using IlmThread::Lock; -using IlmThread::Semaphore; -using IlmThread::Task; -using IlmThread::TaskGroup; -using IlmThread::ThreadPool; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using ILMTHREAD_NAMESPACE::Semaphore; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; + namespace { @@ -92,20 +102,21 @@ struct OutSliceInfo bool zero; OutSliceInfo (PixelType type = HALF, - const char *base = 0, - size_t xStride = 0, - size_t yStride = 0, - int xSampling = 1, - int ySampling = 1, - bool zero = false); + const char *base = 0, + size_t xStride = 0, + size_t yStride = 0, + int xSampling = 1, + int ySampling = 1, + bool zero = false); + }; OutSliceInfo::OutSliceInfo (PixelType t, - const char *b, - size_t xs, size_t ys, - int xsm, int ysm, - bool z) + const char *b, + size_t xs, size_t ys, + int xsm, int ysm, + bool z) : type (t), base (b), @@ -166,11 +177,11 @@ LineBuffer::~LineBuffer () } // namespace - -struct OutputFile::Data: public Mutex +struct OutputFile::Data { Header header; // the image header - int version; // file format version + bool multiPart; // is the file multipart? + int version; // version attribute \todo NOT BEING WRITTEN PROPERLY Int64 previewPosition; // file position for preview FrameBuffer frameBuffer; // framebuffer to write into int currentScanLine; // next scanline to be written @@ -181,38 +192,39 @@ struct OutputFile::Data: public Mutex int minY; // data window's min y coord int maxY; // data window's max x coord vector lineOffsets; // stores offsets in file for - // each scanline + // each scanline vector bytesPerLine; // combined size of a line over // all channels vector offsetInLineBuffer; // offset for each scanline in // its linebuffer Compressor::Format format; // compressor's data format vector slices; // info about channels in file - OStream * os; // file stream to write to - bool deleteStream; Int64 lineOffsetsPosition; // file position for line // offset table - Int64 currentPosition; // current file position vector lineBuffers; // each holds one line buffer int linesInBuffer; // number of scanlines each // buffer holds size_t lineBufferSize; // size of the line buffer - Data (bool deleteStream, int numThreads); + int partNumber; // the output part number + OutputStreamMutex * _streamData; + bool _deleteStream; + Data (int numThreads); ~Data (); inline LineBuffer * getLineBuffer (int number); // hash function from line - // buffer indices into our - // vector of line buffers + // buffer indices into our + // vector of line buffers }; -OutputFile::Data::Data (bool deleteStream, int numThreads): - os (0), - deleteStream (deleteStream), - lineOffsetsPosition (0) +OutputFile::Data::Data (int numThreads): + lineOffsetsPosition (0), + partNumber (-1), + _streamData(0), + _deleteStream(false) { // // We need at least one lineBuffer, but if threading is used, @@ -225,9 +237,6 @@ OutputFile::Data::Data (bool deleteStream, int numThreads): OutputFile::Data::~Data () { - if (deleteStream) - delete os; - for (size_t i = 0; i < lineBuffers.size(); i++) delete lineBuffers[i]; } @@ -239,30 +248,29 @@ OutputFile::Data::getLineBuffer (int number) return lineBuffers[number % lineBuffers.size()]; } - namespace { - Int64 -writeLineOffsets (OStream &os, const vector &lineOffsets) +writeLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const vector &lineOffsets) { Int64 pos = os.tellp(); if (pos == -1) - Iex::throwErrnoExc ("Cannot determine current file position (%T)."); - + IEX_NAMESPACE::throwErrnoExc ("Cannot determine current file position (%T)."); + for (unsigned int i = 0; i < lineOffsets.size(); i++) - Xdr::write (os, lineOffsets[i]); + Xdr::write (os, lineOffsets[i]); return pos; } void -writePixelData (OutputFile::Data *ofd, +writePixelData (OutputStreamMutex *filedata, + OutputFile::Data *partdata, int lineBufferMinY, - const char pixelData[], - int pixelDataSize) + const char pixelData[], + int pixelDataSize) { // // Store a block of pixel data in the output file, and try @@ -270,39 +278,53 @@ writePixelData (OutputFile::Data *ofd, // without calling tellp() (tellp() can be fairly expensive). // - Int64 currentPosition = ofd->currentPosition; - ofd->currentPosition = 0; + Int64 currentPosition = filedata->currentPosition; + filedata->currentPosition = 0; if (currentPosition == 0) - currentPosition = ofd->os->tellp(); + currentPosition = filedata->os->tellp(); - ofd->lineOffsets[(ofd->currentScanLine - ofd->minY) / ofd->linesInBuffer] = - currentPosition; + partdata->lineOffsets[(partdata->currentScanLine - partdata->minY) / partdata->linesInBuffer] = + currentPosition; #ifdef DEBUG - assert (ofd->os->tellp() == currentPosition); + assert (filedata->os->tellp() == currentPosition); #endif + + + + if (partdata->multiPart) + { + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*filedata->os, partdata->partNumber); + } + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*filedata->os, lineBufferMinY); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (*filedata->os, pixelDataSize); + filedata->os->write (pixelData, pixelDataSize); - Xdr::write (*ofd->os, lineBufferMinY); - Xdr::write (*ofd->os, pixelDataSize); - ofd->os->write (pixelData, pixelDataSize); + filedata->currentPosition = currentPosition + + Xdr::size() + + Xdr::size() + + pixelDataSize; - ofd->currentPosition = currentPosition + - Xdr::size() + - Xdr::size() + - pixelDataSize; + if (partdata->multiPart) + { + filedata->currentPosition += Xdr::size(); + } } inline void -writePixelData (OutputFile::Data *ofd, const LineBuffer *lineBuffer) +writePixelData (OutputStreamMutex* filedata, + OutputFile::Data *partdata, + const LineBuffer *lineBuffer) { - writePixelData (ofd, - lineBuffer->minY, + writePixelData (filedata, partdata, + lineBuffer->minY, lineBuffer->dataPtr, - lineBuffer->dataSize); + lineBuffer->dataSize); } @@ -311,7 +333,7 @@ convertToXdr (OutputFile::Data *ofd, Array &lineBuffer, int lineBufferMinY, int lineBufferMaxY, - int /*inSize*/) + int inSize) { // // Convert the contents of a lineBuffer from the machine's native @@ -326,42 +348,25 @@ convertToXdr (OutputFile::Data *ofd, // Xdr representation. This makes it possible to convert the // pixel data in place, without an intermediate temporary buffer. // - - int startY, endY; // The first and last scanlines in - // the file that are in the lineBuffer. - int step; - - if (ofd->lineOrder == INCREASING_Y) - { - startY = max (lineBufferMinY, ofd->minY); - endY = min (lineBufferMaxY, ofd->maxY) + 1; - step = 1; - } - else - { - startY = min (lineBufferMaxY, ofd->maxY); - endY = max (lineBufferMinY, ofd->minY) - 1; - step = -1; - } - + // // Iterate over all scanlines in the lineBuffer to convert. // - for (int y = startY; y != endY; y += step) + char *writePtr = &lineBuffer[0]; + for (int y = lineBufferMinY; y <= lineBufferMaxY; y++) { - // + // // Set these to point to the start of line y. // We will write to writePtr from readPtr. - // + // - char *writePtr = lineBuffer + ofd->offsetInLineBuffer[y - ofd->minY]; const char *readPtr = writePtr; - - // + + // // Iterate over all slices in the file. - // - + // + for (unsigned int i = 0; i < ofd->slices.size(); ++i) { // @@ -377,17 +382,17 @@ convertToXdr (OutputFile::Data *ofd, // // Find the number of sampled pixels, dMaxX-dMinX+1, for - // slice i in scan line y (i.e. pixels within the data window + // slice i in scan line y (i.e. pixels within the data window // for which x % xSampling == 0). // int dMinX = divp (ofd->minX, slice.xSampling); int dMaxX = divp (ofd->maxX, slice.xSampling); - - // + + // // Convert the samples in place. - // - + // + convertInPlace (writePtr, readPtr, slice.type, dMaxX - dMinX + 1); } } @@ -406,11 +411,11 @@ class LineBufferTask: public Task LineBufferTask (TaskGroup *group, OutputFile::Data *ofd, - int number, + int number, int scanLineMin, - int scanLineMax); + int scanLineMax); - virtual ~LineBufferTask (); + virtual ~LineBufferTask (); virtual void execute (); @@ -437,7 +442,7 @@ LineBufferTask::LineBufferTask // _lineBuffer->wait (); - + // // Initialize the lineBuffer data if necessary // @@ -449,11 +454,11 @@ LineBufferTask::LineBufferTask _lineBuffer->minY = _ofd->minY + number * _ofd->linesInBuffer; _lineBuffer->maxY = min (_lineBuffer->minY + _ofd->linesInBuffer - 1, - _ofd->maxY); + _ofd->maxY); _lineBuffer->partiallyFull = true; } - + _lineBuffer->scanLineMin = max (_lineBuffer->minY, scanLineMin); _lineBuffer->scanLineMax = min (_lineBuffer->maxY, scanLineMax); } @@ -476,9 +481,9 @@ LineBufferTask::execute () { // // First copy the pixel data from the - // frame buffer into the line buffer + // frame buffer into the line buffer // - + int yStart, yStop, dy; if (_ofd->lineOrder == INCREASING_Y) @@ -493,8 +498,8 @@ LineBufferTask::execute () yStop = _lineBuffer->scanLineMin - 1; dy = -1; } - - int y; + + int y; for (y = yStart; y != yStop; y += dy) { @@ -502,7 +507,7 @@ LineBufferTask::execute () // Gather one scan line's worth of pixel data and store // them in _ofd->lineBuffer. // - + char *writePtr = _lineBuffer->buffer + _ofd->offsetInLineBuffer[y - _ofd->minY]; // @@ -513,34 +518,34 @@ LineBufferTask::execute () { // // Test if scan line y of this channel contains any data - // (the scan line contains data only if y % ySampling == 0). + // (the scan line contains data only if y % ySampling == 0). // - + const OutSliceInfo &slice = _ofd->slices[i]; - + if (modp (y, slice.ySampling) != 0) continue; - + // // Find the x coordinates of the leftmost and rightmost // sampled pixels (i.e. pixels within the data window // for which x % xSampling == 0). // - + int dMinX = divp (_ofd->minX, slice.xSampling); int dMaxX = divp (_ofd->maxX, slice.xSampling); - + // - // Fill the line buffer with with pixel data. + // Fill the line buffer with with pixel data. // - + if (slice.zero) { // // The frame buffer contains no data for this channel. // Store zeroes in _lineBuffer->buffer. // - + fillChannelWithZeroes (writePtr, _ofd->format, slice.type, dMaxX - dMinX + 1); } @@ -548,51 +553,51 @@ LineBufferTask::execute () { // // If necessary, convert the pixel data to Xdr format. - // Then store the pixel data in _ofd->lineBuffer. + // Then store the pixel data in _ofd->lineBuffer. // - + const char *linePtr = slice.base + divp (y, slice.ySampling) * slice.yStride; - + const char *readPtr = linePtr + dMinX * slice.xStride; const char *endPtr = linePtr + dMaxX * slice.xStride; - + copyFromFrameBuffer (writePtr, readPtr, endPtr, slice.xStride, _ofd->format, slice.type); } } - + if (_lineBuffer->endOfLineBufferData < writePtr) _lineBuffer->endOfLineBufferData = writePtr; - + #ifdef DEBUG - + assert (writePtr - (_lineBuffer->buffer + _ofd->offsetInLineBuffer[y - _ofd->minY]) == (int) _ofd->bytesPerLine[y - _ofd->minY]); - + #endif - + } - + // // If the next scanline isn't past the bounds of the lineBuffer // then we are done, otherwise compress the linebuffer // - + if (y >= _lineBuffer->minY && y <= _lineBuffer->maxY) return; - + _lineBuffer->dataPtr = _lineBuffer->buffer; _lineBuffer->dataSize = _lineBuffer->endOfLineBufferData - _lineBuffer->buffer; - - // + + // // Compress the data - // + // Compressor *compressor = _lineBuffer->compressor; @@ -603,7 +608,7 @@ LineBufferTask::execute () int compSize = compressor->compress (_lineBuffer->dataPtr, _lineBuffer->dataSize, _lineBuffer->minY, compPtr); - + if (compSize < _lineBuffer->dataSize) { _lineBuffer->dataSize = compSize; @@ -617,7 +622,7 @@ LineBufferTask::execute () // native format, so we need to convert the lineBuffer // to Xdr. // - + convertToXdr (_ofd, _lineBuffer->buffer, _lineBuffer->minY, _lineBuffer->maxY, _lineBuffer->dataSize); } @@ -651,68 +656,162 @@ OutputFile::OutputFile const Header &header, int numThreads) : - _data (new Data (true, numThreads)) + _data (new Data (numThreads)) { + _data->_streamData=new OutputStreamMutex (); + _data->_deleteStream=true; try { - header.sanityCheck(); - _data->os = new StdOFStream (fileName); - initialize (header); + header.sanityCheck(); + _data->_streamData->os = new StdOFStream (fileName); + _data->multiPart=false; // only one header, not multipart + initialize (header); + _data->_streamData->currentPosition = _data->_streamData->os->tellp(); + + // Write header and empty offset table to the file. + writeMagicNumberAndVersionField(*_data->_streamData->os, _data->header); + _data->previewPosition = + _data->header.writeTo (*_data->_streamData->os); + _data->lineOffsetsPosition = + writeLineOffsets (*_data->_streamData->os,_data->lineOffsets); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - delete _data; + // ~OutputFile will not run, so free memory here + if (_data) + { + if (_data->_streamData) + { + delete _data->_streamData->os; + delete _data->_streamData; + } - REPLACE_EXC (e, "Cannot open image file " - "\"" << fileName << "\". " << e); - throw; + delete _data; + } + + REPLACE_EXC (e, "Cannot open image file " + "\"" << fileName << "\". " << e.what()); + throw; } catch (...) { - delete _data; + // ~OutputFile will not run, so free memory here + if (_data) + { + if (_data->_streamData) + { + delete _data->_streamData->os; + delete _data->_streamData; + } + delete _data; + } + throw; } } OutputFile::OutputFile - (OStream &os, + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header, int numThreads) : - _data (new Data (false, numThreads)) + _data (new Data (numThreads)) { + _data->_streamData=new OutputStreamMutex (); + _data->_deleteStream=false; try { - header.sanityCheck(); - _data->os = &os; - initialize (header); + header.sanityCheck(); + _data->_streamData->os = &os; + _data->multiPart=false; + initialize (header); + _data->_streamData->currentPosition = _data->_streamData->os->tellp(); + + // Write header and empty offset table to the file. + writeMagicNumberAndVersionField(*_data->_streamData->os, _data->header); + _data->previewPosition = + _data->header.writeTo (*_data->_streamData->os); + _data->lineOffsetsPosition = + writeLineOffsets (*_data->_streamData->os, _data->lineOffsets); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - delete _data; + // ~OutputFile will not run, so free memory here + if (_data) + { + if (_data->_streamData) + delete _data->_streamData; + delete _data; + } - REPLACE_EXC (e, "Cannot open image file " - "\"" << os.fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Cannot open image file " + "\"" << os.fileName() << "\". " << e.what()); + throw; } catch (...) { - delete _data; + // ~OutputFile will not run, so free memory here + if (_data) + { + if (_data->_streamData) + delete _data->_streamData; + delete _data; + } + throw; } } +OutputFile::OutputFile(const OutputPartData* part) : _data(NULL) +{ + try + { + if (part->header.type() != SCANLINEIMAGE) + throw IEX_NAMESPACE::ArgExc("Can't build a OutputFile from a type-mismatched part."); + + _data = new Data (part->numThreads); + _data->_streamData = part->mutex; + _data->_deleteStream=false; + _data->multiPart=part->multipart; + + initialize (part->header); + _data->partNumber = part->partNumber; + _data->lineOffsetsPosition = part->chunkOffsetTablePosition; + _data->previewPosition = part->previewPosition; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + if (_data) delete _data; + + REPLACE_EXC (e, "Cannot initialize output part " + "\"" << part->partNumber << "\". " << e.what()); + throw; + } + catch (...) + { + if (_data) delete _data; + + throw; + } +} void OutputFile::initialize (const Header &header) { _data->header = header; + // "fix" the type if it happens to be set incorrectly + // (attribute is optional, but ensure it is correct if it exists) + if(_data->header.hasType()) + { + _data->header.setType(SCANLINEIMAGE); + } + const Box2i &dataWindow = header.dataWindow(); _data->currentScanLine = (header.lineOrder() == INCREASING_Y)? - dataWindow.min.y: dataWindow.max.y; + dataWindow.min.y: dataWindow.max.y; _data->missingScanLines = dataWindow.max.y - dataWindow.min.y + 1; _data->lineOrder = header.lineOrder(); @@ -722,14 +821,14 @@ OutputFile::initialize (const Header &header) _data->maxY = dataWindow.max.y; size_t maxBytesPerLine = bytesPerLineTable (_data->header, - _data->bytesPerLine); + _data->bytesPerLine); for (size_t i = 0; i < _data->lineBuffers.size(); ++i) { _data->lineBuffers[i] = - new LineBuffer (newCompressor (_data->header.compression(), - maxBytesPerLine, - _data->header)); + new LineBuffer (newCompressor (_data->header.compression(), + maxBytesPerLine, + _data->header)); } LineBuffer *lineBuffer = _data->lineBuffers[0]; @@ -741,21 +840,14 @@ OutputFile::initialize (const Header &header) _data->lineBuffers[i]->buffer.resizeErase(_data->lineBufferSize); int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y + - _data->linesInBuffer) / _data->linesInBuffer; + _data->linesInBuffer) / _data->linesInBuffer; _data->lineOffsets.resize (lineOffsetSize); - + + offsetInLineBufferTable (_data->bytesPerLine, - _data->linesInBuffer, - _data->offsetInLineBuffer); - - _data->previewPosition = - _data->header.writeTo (*_data->os); - - _data->lineOffsetsPosition = - writeLineOffsets (*_data->os, _data->lineOffsets); - - _data->currentPosition = _data->os->tellp(); + _data->linesInBuffer, + _data->offsetInLineBuffer); } @@ -764,12 +856,20 @@ OutputFile::~OutputFile () if (_data) { { + Lock lock(*_data->_streamData); + Int64 originalPosition = _data->_streamData->os->tellp(); + if (_data->lineOffsetsPosition > 0) { try { - _data->os->seekp (_data->lineOffsetsPosition); - writeLineOffsets (*_data->os, _data->lineOffsets); + _data->_streamData->os->seekp (_data->lineOffsetsPosition); + writeLineOffsets (*_data->_streamData->os, _data->lineOffsets); + + // + // Restore the original position. + // + _data->_streamData->os->seekp (originalPosition); } catch (...) { @@ -783,15 +883,22 @@ OutputFile::~OutputFile () } } - delete _data; + if (_data->_deleteStream && _data->_streamData) + delete _data->_streamData->os; + + if (_data->partNumber == -1 && _data->_streamData) + delete _data->_streamData; + + delete _data; } + } const char * OutputFile::fileName () const { - return _data->os->fileName(); + return _data->_streamData->os->fileName(); } @@ -802,11 +909,11 @@ OutputFile::header () const } -void +void OutputFile::setFrameBuffer (const FrameBuffer &frameBuffer) { - Lock lock (*_data); - + Lock lock (*_data->_streamData); + // // Check if the new frame buffer descriptor // is compatible with the image file header. @@ -815,33 +922,33 @@ OutputFile::setFrameBuffer (const FrameBuffer &frameBuffer) const ChannelList &channels = _data->header.channels(); for (ChannelList::ConstIterator i = channels.begin(); - i != channels.end(); - ++i) - { - FrameBuffer::ConstIterator j = frameBuffer.find (i.name()); - - if (j == frameBuffer.end()) - continue; - - if (i.channel().type != j.slice().type) - { - THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" channel " - "of output file \"" << fileName() << "\" is " - "not compatible with the frame buffer's " - "pixel type."); - } - - if (i.channel().xSampling != j.slice().xSampling || - i.channel().ySampling != j.slice().ySampling) + i != channels.end(); + ++i) { - THROW (Iex::ArgExc, "X and/or y subsampling factors " - "of \"" << i.name() << "\" channel " - "of output file \"" << fileName() << "\" are " - "not compatible with the frame buffer's " - "subsampling factors."); - } + FrameBuffer::ConstIterator j = frameBuffer.find (i.name()); + + if (j == frameBuffer.end()) + continue; + + if (i.channel().type != j.slice().type) + { + THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" channel " + "of output file \"" << fileName() << "\" is " + "not compatible with the frame buffer's " + "pixel type."); + } + + if (i.channel().xSampling != j.slice().xSampling || + i.channel().ySampling != j.slice().ySampling) + { + THROW (IEX_NAMESPACE::ArgExc, "X and/or y subsampling factors " + "of \"" << i.name() << "\" channel " + "of output file \"" << fileName() << "\" are " + "not compatible with the frame buffer's " + "subsampling factors."); + } } - + // // Initialize slice table for writePixels(). // @@ -849,40 +956,40 @@ OutputFile::setFrameBuffer (const FrameBuffer &frameBuffer) vector slices; for (ChannelList::ConstIterator i = channels.begin(); - i != channels.end(); - ++i) - { - FrameBuffer::ConstIterator j = frameBuffer.find (i.name()); - - if (j == frameBuffer.end()) - { - // - // Channel i is not present in the frame buffer. - // In the file, channel i will contain only zeroes. - // - - slices.push_back (OutSliceInfo (i.channel().type, - 0, // base - 0, // xStride, - 0, // yStride, - i.channel().xSampling, - i.channel().ySampling, - true)); // zero - } - else + i != channels.end(); + ++i) { - // - // Channel i is present in the frame buffer. - // - - slices.push_back (OutSliceInfo (j.slice().type, - j.slice().base, - j.slice().xStride, - j.slice().yStride, - j.slice().xSampling, - j.slice().ySampling, - false)); // zero - } + FrameBuffer::ConstIterator j = frameBuffer.find (i.name()); + + if (j == frameBuffer.end()) + { + // + // Channel i is not present in the frame buffer. + // In the file, channel i will contain only zeroes. + // + + slices.push_back (OutSliceInfo (i.channel().type, + 0, // base + 0, // xStride, + 0, // yStride, + i.channel().xSampling, + i.channel().ySampling, + true)); // zero + } + else + { + // + // Channel i is present in the frame buffer. + // + + slices.push_back (OutSliceInfo (j.slice().type, + j.slice().base, + j.slice().xStride, + j.slice().yStride, + j.slice().xSampling, + j.slice().ySampling, + false)); // zero + } } // @@ -897,21 +1004,21 @@ OutputFile::setFrameBuffer (const FrameBuffer &frameBuffer) const FrameBuffer & OutputFile::frameBuffer () const { - Lock lock (*_data); + Lock lock (*_data->_streamData); return _data->frameBuffer; } -void +void OutputFile::writePixels (int numScanLines) { try { - Lock lock (*_data); + Lock lock (*_data->_streamData); - if (_data->slices.size() == 0) - throw Iex::ArgExc ("No frame buffer specified " - "as pixel data source."); + if (_data->slices.size() == 0) + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data source."); // // Maintain two iterators: @@ -933,37 +1040,37 @@ OutputFile::writePixels (int numScanLines) // // Create a task group for all line buffer tasks. When the // taskgroup goes out of scope, the destructor waits until - // all tasks are complete. + // all tasks are complete. // - + TaskGroup taskGroup; - + // // Determine the range of lineBuffers that intersect the scan - // line range. Then add the initial compression tasks to the - // thread pool. We always add in at least one task but the - // individual task might not do anything if numScanLines == 0. + // line range. Then add the initial compression tasks to the + // thread pool. We always add in at least one task but the + // individual task might not do anything if numScanLines == 0. // - + if (_data->lineOrder == INCREASING_Y) { int last = (_data->currentScanLine + (numScanLines - 1) - _data->minY) / _data->linesInBuffer; - + scanLineMin = _data->currentScanLine; scanLineMax = _data->currentScanLine + numScanLines - 1; - + int numTasks = max (min ((int)_data->lineBuffers.size(), last - first + 1), - 1); + 1); for (int i = 0; i < numTasks; i++) - { + { ThreadPool::addGlobalTask (new LineBufferTask (&taskGroup, _data, first + i, scanLineMin, scanLineMax)); - } - + } + nextCompressBuffer = first + numTasks; stop = last + 1; step = 1; @@ -972,173 +1079,173 @@ OutputFile::writePixels (int numScanLines) { int last = (_data->currentScanLine - (numScanLines - 1) - _data->minY) / _data->linesInBuffer; - + scanLineMax = _data->currentScanLine; scanLineMin = _data->currentScanLine - numScanLines + 1; - + int numTasks = max (min ((int)_data->lineBuffers.size(), first - last + 1), - 1); + 1); for (int i = 0; i < numTasks; i++) - { + { ThreadPool::addGlobalTask (new LineBufferTask (&taskGroup, _data, first - i, scanLineMin, scanLineMax)); - } - + } + nextCompressBuffer = first - numTasks; stop = last - 1; step = -1; } - + while (true) { if (_data->missingScanLines <= 0) { - throw Iex::ArgExc ("Tried to write more scan lines " + throw IEX_NAMESPACE::ArgExc ("Tried to write more scan lines " "than specified by the data window."); } - - // + + // // Wait until the next line buffer is ready to be written - // + // LineBuffer *writeBuffer = - _data->getLineBuffer (nextWriteBuffer); + _data->getLineBuffer (nextWriteBuffer); writeBuffer->wait(); - - int numLines = writeBuffer->scanLineMax - + + int numLines = writeBuffer->scanLineMax - writeBuffer->scanLineMin + 1; _data->missingScanLines -= numLines; - - // + + // // If the line buffer is only partially full, then it is - // not complete and we cannot write it to disk yet. - // + // not complete and we cannot write it to disk yet. + // if (writeBuffer->partiallyFull) { _data->currentScanLine = _data->currentScanLine + step * numLines; writeBuffer->post(); - + return; } - - // + + // // Write the line buffer - // + // - writePixelData (_data, writeBuffer); + writePixelData (_data->_streamData, _data, writeBuffer); nextWriteBuffer += step; _data->currentScanLine = _data->currentScanLine + step * numLines; - + #ifdef DEBUG - + assert (_data->currentScanLine == ((_data->lineOrder == INCREASING_Y) ? writeBuffer->scanLineMax + 1: writeBuffer->scanLineMin - 1)); - + #endif - - // + + // // Release the lock on the line buffer - // + // writeBuffer->post(); - - // + + // // If this was the last line buffer in the scanline range - // + // if (nextWriteBuffer == stop) break; - - // + + // // If there are no more line buffers to compress, // then only continue to write out remaining lineBuffers - // + // if (nextCompressBuffer == stop) continue; - - // + + // // Add nextCompressBuffer as a compression task - // + // ThreadPool::addGlobalTask (new LineBufferTask (&taskGroup, _data, nextCompressBuffer, scanLineMin, scanLineMax)); - - // + + // // Update the next line buffer we need to compress - // + // nextCompressBuffer += step; } - - // + + // // Finish all tasks - // + // } - - // - // Exeption handling: - // - // LineBufferTask::execute() may have encountered exceptions, but - // those exceptions occurred in another thread, not in the thread - // that is executing this call to OutputFile::writePixels(). - // LineBufferTask::execute() has caught all exceptions and stored - // the exceptions' what() strings in the line buffers. - // Now we check if any line buffer contains a stored exception; if - // this is the case then we re-throw the exception in this thread. - // (It is possible that multiple line buffers contain stored - // exceptions. We re-throw the first exception we find and - // ignore all others.) - // - - const string *exception = 0; - - for (int i = 0; i < _data->lineBuffers.size(); ++i) - { + + // + // Exeption handling: + // + // LineBufferTask::execute() may have encountered exceptions, but + // those exceptions occurred in another thread, not in the thread + // that is executing this call to OutputFile::writePixels(). + // LineBufferTask::execute() has caught all exceptions and stored + // the exceptions' what() strings in the line buffers. + // Now we check if any line buffer contains a stored exception; if + // this is the case then we re-throw the exception in this thread. + // (It is possible that multiple line buffers contain stored + // exceptions. We re-throw the first exception we find and + // ignore all others.) + // + + const string *exception = 0; + + for (size_t i = 0; i < _data->lineBuffers.size(); ++i) + { LineBuffer *lineBuffer = _data->lineBuffers[i]; - if (lineBuffer->hasException && !exception) - exception = &lineBuffer->exception; + if (lineBuffer->hasException && !exception) + exception = &lineBuffer->exception; - lineBuffer->hasException = false; - } + lineBuffer->hasException = false; + } - if (exception) - throw Iex::IoExc (*exception); + if (exception) + throw IEX_NAMESPACE::IoExc (*exception); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Failed to write pixel data to image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Failed to write pixel data to image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } -int +int OutputFile::currentScanLine () const { - Lock lock (*_data); + Lock lock (*_data->_streamData); return _data->currentScanLine; } -void +void OutputFile::copyPixels (InputFile &in) { - Lock lock (*_data); + Lock lock (*_data->_streamData); // // Check if this file's and and the InputFile's @@ -1149,36 +1256,36 @@ OutputFile::copyPixels (InputFile &in) const Header &inHdr = in.header(); if (inHdr.find("tiles") != inHdr.end()) - THROW (Iex::ArgExc, "Cannot copy pixels from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\". " + THROW (IEX_NAMESPACE::ArgExc, "Cannot copy pixels from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\". " "The input file is tiled, but the output file is " "not. Try using TiledOutputFile::copyPixels " "instead."); if (!(hdr.dataWindow() == inHdr.dataWindow())) - THROW (Iex::ArgExc, "Cannot copy pixels from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\". " + THROW (IEX_NAMESPACE::ArgExc, "Cannot copy pixels from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\". " "The files have different data windows."); if (!(hdr.lineOrder() == inHdr.lineOrder())) - THROW (Iex::ArgExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\" failed. " - "The files have different line orders."); + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files have different line orders."); if (!(hdr.compression() == inHdr.compression())) - THROW (Iex::ArgExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\" failed. " - "The files use different compression methods."); + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files use different compression methods."); if (!(hdr.channels() == inHdr.channels())) - THROW (Iex::ArgExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\" failed. " - "The files have different channel lists."); + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files have different channel lists."); // // Verify that no pixel data have been written to this file yet. @@ -1187,11 +1294,11 @@ OutputFile::copyPixels (InputFile &in) const Box2i &dataWindow = hdr.dataWindow(); if (_data->missingScanLines != dataWindow.max.y - dataWindow.min.y + 1) - THROW (Iex::LogicExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\" failed. " - "\"" << fileName() << "\" already contains " - "pixel data."); + THROW (IEX_NAMESPACE::LogicExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "\"" << fileName() << "\" already contains " + "pixel data."); // // Copy the pixel data. @@ -1199,47 +1306,55 @@ OutputFile::copyPixels (InputFile &in) while (_data->missingScanLines > 0) { - const char *pixelData; - int pixelDataSize; + const char *pixelData; + int pixelDataSize; - in.rawPixelData (_data->currentScanLine, pixelData, pixelDataSize); + in.rawPixelData (_data->currentScanLine, pixelData, pixelDataSize); - writePixelData (_data, lineBufferMinY (_data->currentScanLine, - _data->minY, - _data->linesInBuffer), + writePixelData (_data->_streamData, _data, lineBufferMinY (_data->currentScanLine, + _data->minY, + _data->linesInBuffer), pixelData, pixelDataSize); - _data->currentScanLine += (_data->lineOrder == INCREASING_Y)? - _data->linesInBuffer: -_data->linesInBuffer; + _data->currentScanLine += (_data->lineOrder == INCREASING_Y)? + _data->linesInBuffer: -_data->linesInBuffer; - _data->missingScanLines -= _data->linesInBuffer; + _data->missingScanLines -= _data->linesInBuffer; } } +void +OutputFile::copyPixels( InputPart & in) +{ + copyPixels(*in.file); +} + + + void OutputFile::updatePreviewImage (const PreviewRgba newPixels[]) { - Lock lock (*_data); + Lock lock (*_data->_streamData); if (_data->previewPosition <= 0) - THROW (Iex::LogicExc, "Cannot update preview image pixels. " - "File \"" << fileName() << "\" does not " - "contain a preview image."); + THROW (IEX_NAMESPACE::LogicExc, "Cannot update preview image pixels. " + "File \"" << fileName() << "\" does not " + "contain a preview image."); // // Store the new pixels in the header's preview image attribute. // PreviewImageAttribute &pia = - _data->header.typedAttribute ("preview"); + _data->header.typedAttribute ("preview"); PreviewImage &pi = pia.value(); PreviewRgba *pixels = pi.pixels(); int numPixels = pi.width() * pi.height(); for (int i = 0; i < numPixels; ++i) - pixels[i] = newPixels[i]; + pixels[i] = newPixels[i]; // // Save the current file position, jump to the position in @@ -1247,42 +1362,42 @@ OutputFile::updatePreviewImage (const PreviewRgba newPixels[]) // preview image, and jump back to the saved file position. // - Int64 savedPosition = _data->os->tellp(); + Int64 savedPosition = _data->_streamData->os->tellp(); try { - _data->os->seekp (_data->previewPosition); - pia.writeValueTo (*_data->os, _data->version); - _data->os->seekp (savedPosition); + _data->_streamData->os->seekp (_data->previewPosition); + pia.writeValueTo (*_data->_streamData->os, _data->version); + _data->_streamData->os->seekp (savedPosition); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Cannot update preview image pixels for " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Cannot update preview image pixels for " + "file \"" << fileName() << "\". " << e.what()); + throw; } } -void +void OutputFile::breakScanLine (int y, int offset, int length, char c) { - Lock lock (*_data); + Lock lock (*_data->_streamData); - Int64 position = - _data->lineOffsets[(y - _data->minY) / _data->linesInBuffer]; + Int64 position = + _data->lineOffsets[(y - _data->minY) / _data->linesInBuffer]; if (!position) - THROW (Iex::ArgExc, "Cannot overwrite scan line " << y << ". " - "The scan line has not yet been stored in " - "file \"" << fileName() << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "Cannot overwrite scan line " << y << ". " + "The scan line has not yet been stored in " + "file \"" << fileName() << "\"."); - _data->currentPosition = 0; - _data->os->seekp (position + offset); + _data->_streamData->currentPosition = 0; + _data->_streamData->os->seekp (position + offset); for (int i = 0; i < length; ++i) - _data->os->write (&c, 1); + _data->_streamData->os->write (&c, 1); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfOutputFile.h b/3rdparty/openexr/IlmImf/ImfOutputFile.h index ed7b98b516..54d8baf027 100644 --- a/3rdparty/openexr/IlmImf/ImfOutputFile.h +++ b/3rdparty/openexr/IlmImf/ImfOutputFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,17 +43,18 @@ // //----------------------------------------------------------------------------- -#include -#include -#include +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfThreading.h" +#include "ImfGenericOutputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -class InputFile; -struct PreviewRgba; - -class OutputFile +class OutputFile : public GenericOutputFile { public: @@ -68,6 +69,7 @@ class OutputFile // used to write the file (see ImfThreading.h). //----------------------------------------------------------- + IMF_EXPORT OutputFile (const char fileName[], const Header &header, int numThreads = globalThreadCount()); @@ -84,7 +86,8 @@ class OutputFile // used to write the file (see ImfThreading.h). //------------------------------------------------------------ - OutputFile (OStream &os, const Header &header, + IMF_EXPORT + OutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header, int numThreads = globalThreadCount()); @@ -96,6 +99,7 @@ class OutputFile // an incomplete file. //------------------------------------------------- + IMF_EXPORT virtual ~OutputFile (); @@ -103,6 +107,7 @@ class OutputFile // Access to the file name //------------------------ + IMF_EXPORT const char * fileName () const; @@ -110,6 +115,7 @@ class OutputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; @@ -124,6 +130,7 @@ class OutputFile // after each call to writePixels. //------------------------------------------------------- + IMF_EXPORT void setFrameBuffer (const FrameBuffer &frameBuffer); @@ -131,6 +138,7 @@ class OutputFile // Access to the current frame buffer //----------------------------------- + IMF_EXPORT const FrameBuffer & frameBuffer () const; @@ -147,6 +155,7 @@ class OutputFile // header().dataWindow().max.y - header().dataWindow().min.y + 1. //------------------------------------------------------------------- + IMF_EXPORT void writePixels (int numScanLines = 1); @@ -171,6 +180,7 @@ class OutputFile // //------------------------------------------------------------------ + IMF_EXPORT int currentScanLine () const; @@ -182,7 +192,17 @@ class OutputFile // "lineOrder" and "channels" attributes must be the same. //-------------------------------------------------------------- + IMF_EXPORT void copyPixels (InputFile &in); + + //------------------------------------------------------------- + // Shortcut to copy all pixels from an InputPart into this file + // - equivalent to copyPixel(InputFile &in) but for multipart files + //--------------------------------------------------------------- + + IMF_EXPORT + void copyPixels (InputPart &in); + //-------------------------------------------------------------- @@ -191,7 +211,7 @@ class OutputFile // updatePreviewImage() supplies a new set of pixels for the // preview image attribute in the file's header. If the header // does not contain a preview image, updatePreviewImage() throws - // an Iex::LogicExc. + // an IEX_NAMESPACE::LogicExc. // // Note: updatePreviewImage() is necessary because images are // often stored in a file incrementally, a few scan lines at a @@ -203,12 +223,13 @@ class OutputFile // //-------------------------------------------------------------- + IMF_EXPORT void updatePreviewImage (const PreviewRgba newPixels[]); //--------------------------------------------------------- // Break a scan line -- for testing and debugging only: - // + // // breakScanLine(y,p,n,c) introduces an error into the // output file by writing n copies of character c, starting // p bytes from the beginning of the pixel data block that @@ -220,6 +241,7 @@ class OutputFile // //--------------------------------------------------------- + IMF_EXPORT void breakScanLine (int y, int offset, int length, char c); @@ -227,15 +249,28 @@ class OutputFile private: + //------------------------------------------------------------ + // Constructor -- attaches the OutputStreamMutex to the + // given one from MultiPartOutputFile. Set the previewPosition + // and lineOffsetsPosition which have been acquired from + // the constructor of MultiPartOutputFile as well. + //------------------------------------------------------------ + OutputFile (const OutputPartData* part); + OutputFile (const OutputFile &); // not implemented OutputFile & operator = (const OutputFile &); // not implemented void initialize (const Header &header); Data * _data; + + + friend class MultiPartOutputFile; + }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + #endif diff --git a/3rdparty/openexr/IlmImf/ImfOutputPart.cpp b/3rdparty/openexr/IlmImf/ImfOutputPart.cpp new file mode 100644 index 0000000000..920b4d3376 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfOutputPart.cpp @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfOutputPart.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +OutputPart::OutputPart(MultiPartOutputFile& multiPartFile, int partNumber) +{ + file = multiPartFile.getOutputPart(partNumber); +} + +const char * +OutputPart::fileName () const +{ + return file->fileName(); +} + +const Header & +OutputPart::header () const +{ + return file->header(); +} + +void +OutputPart::setFrameBuffer (const FrameBuffer &frameBuffer) +{ + file->setFrameBuffer(frameBuffer); +} + +const FrameBuffer & +OutputPart::frameBuffer () const +{ + return file->frameBuffer(); +} + +void +OutputPart::writePixels (int numScanLines) +{ + file->writePixels(numScanLines); +} + +int +OutputPart::currentScanLine () const +{ + return file->currentScanLine(); +} + +void +OutputPart::copyPixels (InputFile &in) +{ + file->copyPixels(in); +} + +void +OutputPart::copyPixels (InputPart &in) +{ + file->copyPixels(in); +} + +void +OutputPart::updatePreviewImage (const PreviewRgba newPixels[]) +{ + file->updatePreviewImage(newPixels); +} + +void +OutputPart::breakScanLine (int y, int offset, int length, char c) +{ + file->breakScanLine(y, offset, length, c); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfOutputPart.h b/3rdparty/openexr/IlmImf/ImfOutputPart.h new file mode 100644 index 0000000000..730396bf62 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfOutputPart.h @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFOUTPUTPART_H_ +#define IMFOUTPUTPART_H_ + +#include "ImfMultiPartOutputFile.h" +#include "ImfOutputFile.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +//--------------------------------------------------------------------- +// class OutputPart: +// +// Same interface as OutputFile. Please refer to OutputFile. +//--------------------------------------------------------------------- + +class OutputPart +{ + public: + IMF_EXPORT + OutputPart(MultiPartOutputFile& multiPartFile, int partNumber); + + IMF_EXPORT + const char * fileName () const; + IMF_EXPORT + const Header & header () const; + IMF_EXPORT + void setFrameBuffer (const FrameBuffer &frameBuffer); + IMF_EXPORT + const FrameBuffer & frameBuffer () const; + IMF_EXPORT + void writePixels (int numScanLines = 1); + IMF_EXPORT + int currentScanLine () const; + IMF_EXPORT + void copyPixels (InputFile &in); + IMF_EXPORT + void copyPixels (InputPart &in); + + IMF_EXPORT + void updatePreviewImage (const PreviewRgba newPixels[]); + IMF_EXPORT + void breakScanLine (int y, int offset, int length, char c); + + private: + OutputFile* file; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFOUTPUTPART_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfOutputPartData.cpp b/3rdparty/openexr/IlmImf/ImfOutputPartData.cpp new file mode 100644 index 0000000000..b517a476a5 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfOutputPartData.cpp @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfOutputPartData.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + + +OutputPartData::OutputPartData(OutputStreamMutex* mutex, const Header &header, + int partNumber, int numThreads, bool multipart): + header(header), + numThreads(numThreads), + partNumber(partNumber), + multipart(multipart), + mutex(mutex) +{ +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfOutputPartData.h b/3rdparty/openexr/IlmImf/ImfOutputPartData.h new file mode 100644 index 0000000000..67dcb590ce --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfOutputPartData.h @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFOUTPUTPARTDATA_H_ +#define IMFOUTPUTPARTDATA_H_ + +#include "ImfHeader.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +struct OutputPartData +{ + Header header; + Int64 chunkOffsetTablePosition; + Int64 previewPosition; + int numThreads; + int partNumber; + bool multipart; + OutputStreamMutex* mutex; + + IMF_EXPORT + OutputPartData(OutputStreamMutex* mutex, const Header &header, + int partNumber, int numThreads, bool multipart); + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFOUTPUTPARTDATA_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfOutputStreamMutex.h b/3rdparty/openexr/IlmImf/ImfOutputStreamMutex.h new file mode 100644 index 0000000000..bf5e1c392b --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfOutputStreamMutex.h @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFOUTPUTSTREAMMUTEX_H_ +#define IMFOUTPUTSTREAMMUTEX_H_ + +#include + +#include "ImfIO.h" +#include "IlmThreadMutex.h" +#include "ImfGenericOutputFile.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +using ILMTHREAD_NAMESPACE::Mutex; + +// +// Used to wrap OPENEXR_IMF_INTERNAL_NAMESPACE::OStream as a Mutex. +// +struct OutputStreamMutex : public Mutex +{ + OPENEXR_IMF_INTERNAL_NAMESPACE::OStream* os; + Int64 currentPosition; + + OutputStreamMutex() + { + os = 0; + currentPosition = 0; + } +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + + +#endif /* IMFOUTPUTSTREAMMUTEX_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfPartHelper.h b/3rdparty/openexr/IlmImf/ImfPartHelper.h new file mode 100644 index 0000000000..d55cc7b43c --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfPartHelper.h @@ -0,0 +1,262 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Weta Digital Ltd +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Weta Digital nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + +#ifndef INCLUDED_IMF_PARTHELPER_H +#define INCLUDED_IMF_PARTHELPER_H + +//----------------------------------------------------------------------------- +// +// Functions to help split channels into separate parts: provide a list of +// channels, with desired views. call SplitChannels to assign a part to each +// layer, or correct the name of the channel. +// Also can enumerate the parts in a file and list which parts channels are in +// +// This is a good way to offer a 'create Multipart file' checkbox to the user in a +// write dialog box: Populate a list of MultiViewChannelName objects, +// call SplitChannels with whether single or multipart files are required. +// Then write the number of parts it specifies, using internal_name for the channel +// names in the ChannelList and FrameBuffer objects. There should be no need +// for different codepaths for single part and multipart files +// +// Similarly, on reading a file as a MultiPartInputFile, use GetChannelsInMultiPartFile to +// enumerate all channels in the file, using internal_name in FrameBuffer objects +// to read the channel +// +// +//----------------------------------------------------------------------------- + +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfMultiPartInputFile.h" +#include "ImfChannelList.h" +#include "ImfStringVectorAttribute.h" +#include "ImfStandardAttributes.h" +#include "ImfMultiView.h" + +#include +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +struct MultiViewChannelName{ + +public: + std::string name; ///< name of channel + std::string view; ///< view for channel + + int part_number; ///< part number: updated by SplitChannels + std::string internal_name;///< name used in headers: in singlepart mode, may contain viewname + + virtual ~MultiViewChannelName() {} + + //return layer for this channel, or "" if no layer + std::string getLayer() const + { + std::size_t q=name.rfind('.'); + if( q==name.npos ) + { + return ""; + } + return name.substr(0,q); + + } + + std::string getSuffix() const + { + std::size_t q=name.rfind('.'); + if( q==name.npos ) + { + return name; + } + return name.substr(q+1); + + } + +}; + + + +// +///\brief assigns individual channels to different parts based on their layer and view name +/// input is an array, list, vector etc of MultiViewChannelName objects +/// on entry, each MultiViewChannelName name/view must be set (view can be empty if not multiview) +/// +/// if singlepart set, then on exit part_number will be zero, and internal_name will have view name inserted +/// otherwise, each channel will be assigned to a different part based on its layer name and view name +/// +/// @param begin pointer to first MultiViewChannelName item +/// @param end pointer to end of MultiViewChannelName item array +/// @return total number of parts required +// + +template int +SplitChannels(const T & begin,const T & end,bool multipart=true,const std::string & heroView="") +{ + if(!multipart) + { + for(T i=begin;i!=end;i++) + { + i->part_number=0; + + //does this have a view name set? + if(i->view=="") + { + i->internal_name=i->name; + }else{ + + std::string lname = i->getLayer(); + + // no layer, only non-hero views get view name in layer name + + + if(lname=="") + { + if(i->view==heroView) + { + i->internal_name = i->name; + }else{ + i->internal_name = i->view+"."+i->name; + } + }else{ + i->internal_name = lname+"."+i->view+"."+i->getSuffix(); + } + } + } + // single part created + return 1; + }else{ + // step 1: extract individual layers and parts + // for each layer, enumerate which views are active + + std::map< std::string , std::set< std::string > > viewsInLayers; + for(T i=begin;i!=end;i++) + { + viewsInLayers[i->getLayer()].insert(i->view); + } + + // step 2: assign a part number to each layer/view + + std::map< std::pair , int > layerToPart; + + int partCount=0; + + for(std::map< std::string , std::set< std::string > >::const_iterator layer=viewsInLayers.begin(); + layer!=viewsInLayers.end();layer++) + { + // if this layer has a heroView, insert that first + bool layer_has_hero = layer->second.find(heroView)!=layer->second.end(); + if( layer_has_hero ) + { + layerToPart[ std::make_pair(layer->first,heroView) ] = partCount++; + } + + + // insert other layers which aren't the hero view + for(std::set< std::string >::const_iterator view=layer->second.begin(); + view!=layer->second.end();view++) + { + if(*view!=heroView) + { + layerToPart[ std::make_pair(layer->first,*view) ] = partCount++; + } + } + + } + + // step 3: update part number of each provided channel + + for( T i=begin;i!=end;i++) + { + i->internal_name=i->name; + i->part_number = layerToPart[ std::make_pair(i->getLayer(),i->view) ]; + } + + + // return number of parts created + return partCount; + } +} + +// +// populate the chans vector with a list of channels in the file +// and their corresponding part number +// +template void +GetChannelsInMultiPartFile(const MultiPartInputFile & file,T & chans) +{ + bool has_multiview=false; + StringVector mview; + if(file.parts()==1) + { + if(hasMultiView(file.header(0))) + { + mview=multiView(file.header(0)); + has_multiview=true; + } + } + + for(int p=0;p +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using std::string; + +bool isImage(const string& name) +{ + return (name == SCANLINEIMAGE || name == TILEDIMAGE); +} + +bool isTiled(const string& name) +{ + return (name == TILEDIMAGE || name == DEEPTILE); +} + +bool isDeepData(const string& name) +{ + return (name == DEEPTILE || name == DEEPSCANLINE); +} + +bool isSupportedType(const string& name) +{ + return (name == SCANLINEIMAGE || name == TILEDIMAGE || + name == DEEPSCANLINE || name == DEEPTILE); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfPartType.h b/3rdparty/openexr/IlmImf/ImfPartType.h new file mode 100644 index 0000000000..423bce038c --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfPartType.h @@ -0,0 +1,62 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFPARTTYPE_H_ +#define IMFPARTTYPE_H_ + +#include +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +const std::string SCANLINEIMAGE = "scanlineimage"; +const std::string TILEDIMAGE = "tiledimage"; +const std::string DEEPSCANLINE = "deepscanline"; +const std::string DEEPTILE = "deeptile"; + +IMF_EXPORT bool isImage(const std::string& name); + +IMF_EXPORT bool isTiled(const std::string& name); + +IMF_EXPORT bool isDeepData(const std::string& name); + +IMF_EXPORT bool isSupportedType(const std::string& name); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif /* IMFPARTTYPE_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfPixelType.h b/3rdparty/openexr/IlmImf/ImfPixelType.h index 468e807cd2..4b8005e95c 100644 --- a/3rdparty/openexr/IlmImf/ImfPixelType.h +++ b/3rdparty/openexr/IlmImf/ImfPixelType.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,19 +43,25 @@ // //----------------------------------------------------------------------------- -namespace Imf { +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER enum PixelType { - UINT = 0, // unsigned int (32 bit) - HALF = 1, // half (16 bit floating point) - FLOAT = 2, // float (32 bit floating point) + UINT = 0, // unsigned int (32 bit) + HALF = 1, // half (16 bit floating point) + FLOAT = 2, // float (32 bit floating point) NUM_PIXELTYPES // number of different pixel types }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfPizCompressor.cpp b/3rdparty/openexr/IlmImf/ImfPizCompressor.cpp index b0c0bb2eda..8b3ee38c3c 100644 --- a/3rdparty/openexr/IlmImf/ImfPizCompressor.cpp +++ b/3rdparty/openexr/IlmImf/ImfPizCompressor.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,29 +39,30 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include +#include "ImfPizCompressor.h" +#include "ImfHeader.h" +#include "ImfChannelList.h" +#include "ImfHuf.h" +#include "ImfWav.h" +#include "ImfMisc.h" +#include "ImfCheckedArithmetic.h" #include #include #include -#include -#include -#include +#include "ImfIO.h" +#include "ImfXdr.h" +#include "ImfAutoArray.h" #include #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -using Imath::divp; -using Imath::modp; -using Imath::Box2i; -using Imath::V2i; -using Iex::InputExc; +using IMATH_NAMESPACE::divp; +using IMATH_NAMESPACE::modp; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::V2i; +using IEX_NAMESPACE::InputExc; namespace { @@ -74,48 +75,48 @@ const int BITMAP_SIZE = (USHORT_RANGE >> 3); void bitmapFromData (const unsigned short data[/*nData*/], - int nData, - unsigned char bitmap[BITMAP_SIZE], - unsigned short &minNonZero, - unsigned short &maxNonZero) + int nData, + unsigned char bitmap[BITMAP_SIZE], + unsigned short &minNonZero, + unsigned short &maxNonZero) { for (int i = 0; i < BITMAP_SIZE; ++i) - bitmap[i] = 0; + bitmap[i] = 0; for (int i = 0; i < nData; ++i) - bitmap[data[i] >> 3] |= (1 << (data[i] & 7)); + bitmap[data[i] >> 3] |= (1 << (data[i] & 7)); bitmap[0] &= ~1; // zero is not explicitly stored in - // the bitmap; we assume that the - // data always contain zeroes + // the bitmap; we assume that the + // data always contain zeroes minNonZero = BITMAP_SIZE - 1; maxNonZero = 0; for (int i = 0; i < BITMAP_SIZE; ++i) { - if (bitmap[i]) - { - if (minNonZero > i) - minNonZero = i; - if (maxNonZero < i) - maxNonZero = i; - } + if (bitmap[i]) + { + if (minNonZero > i) + minNonZero = i; + if (maxNonZero < i) + maxNonZero = i; + } } } unsigned short forwardLutFromBitmap (const unsigned char bitmap[BITMAP_SIZE], - unsigned short lut[USHORT_RANGE]) + unsigned short lut[USHORT_RANGE]) { int k = 0; for (int i = 0; i < USHORT_RANGE; ++i) { - if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) - lut[i] = k++; - else - lut[i] = 0; + if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) + lut[i] = k++; + else + lut[i] = 0; } return k - 1; // maximum value stored in lut[], @@ -124,20 +125,20 @@ forwardLutFromBitmap (const unsigned char bitmap[BITMAP_SIZE], unsigned short reverseLutFromBitmap (const unsigned char bitmap[BITMAP_SIZE], - unsigned short lut[USHORT_RANGE]) + unsigned short lut[USHORT_RANGE]) { int k = 0; for (int i = 0; i < USHORT_RANGE; ++i) { - if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) - lut[k++] = i; + if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7)))) + lut[k++] = i; } int n = k - 1; while (k < USHORT_RANGE) - lut[k++] = 0; + lut[k++] = 0; return n; // maximum k where lut[k] is non-zero, } // i.e. number of ones in bitmap minus 1 @@ -145,11 +146,11 @@ reverseLutFromBitmap (const unsigned char bitmap[BITMAP_SIZE], void applyLut (const unsigned short lut[USHORT_RANGE], - unsigned short data[/*nData*/], - int nData) + unsigned short data[/*nData*/], + int nData) { for (int i = 0; i < nData; ++i) - data[i] = lut[data[i]]; + data[i] = lut[data[i]]; } @@ -198,15 +199,15 @@ PizCompressor::PizCompressor bool onlyHalfChannels = true; for (ChannelList::ConstIterator c = channels.begin(); - c != channels.end(); - ++c) + c != channels.end(); + ++c) { - _numChans++; + _numChans++; - assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0); + assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0); - if (c.channel().type != HALF) - onlyHalfChannels = false; + if (c.channel().type != HALF) + onlyHalfChannels = false; } _channelData = new ChannelData[_numChans]; @@ -224,7 +225,7 @@ PizCompressor::PizCompressor // if (onlyHalfChannels && (sizeof (half) == pixelTypeSize (HALF))) - _format = NATIVE; + _format = NATIVE; } @@ -252,23 +253,23 @@ PizCompressor::format () const int PizCompressor::compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { return compress (inPtr, - inSize, - Box2i (V2i (_minX, minY), - V2i (_maxX, minY + numScanLines() - 1)), - outPtr); + inSize, + Box2i (V2i (_minX, minY), + V2i (_maxX, minY + numScanLines() - 1)), + outPtr); } int PizCompressor::compressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr) + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) { return compress (inPtr, inSize, range, outPtr); } @@ -276,23 +277,23 @@ PizCompressor::compressTile (const char *inPtr, int PizCompressor::uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { return uncompress (inPtr, - inSize, - Box2i (V2i (_minX, minY), - V2i (_maxX, minY + numScanLines() - 1)), - outPtr); + inSize, + Box2i (V2i (_minX, minY), + V2i (_maxX, minY + numScanLines() - 1)), + outPtr); } int PizCompressor::uncompressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr) + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) { return uncompress (inPtr, inSize, range, outPtr); } @@ -300,9 +301,9 @@ PizCompressor::uncompressTile (const char *inPtr, int PizCompressor::compress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr) + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) { // // This is the compress function which is used by both the tiled and @@ -310,13 +311,13 @@ PizCompressor::compress (const char *inPtr, // // - // Special case ­- empty input buffer + // Special case ďż˝- empty input buffer // if (inSize == 0) { - outPtr = _outBuffer; - return 0; + outPtr = _outBuffer; + return 0; } // @@ -333,10 +334,10 @@ PizCompressor::compress (const char *inPtr, int maxX = range.max.x; int minY = range.min.y; int maxY = range.max.y; - + if (maxY > _maxY) maxY = _maxY; - + if (maxX > _maxX) maxX = _maxX; @@ -344,75 +345,75 @@ PizCompressor::compress (const char *inPtr, int i = 0; for (ChannelList::ConstIterator c = _channels.begin(); - c != _channels.end(); - ++c, ++i) + c != _channels.end(); + ++c, ++i) { - ChannelData &cd = _channelData[i]; + ChannelData &cd = _channelData[i]; - cd.start = tmpBufferEnd; - cd.end = cd.start; + cd.start = tmpBufferEnd; + cd.end = cd.start; - cd.nx = numSamples (c.channel().xSampling, minX, maxX); - cd.ny = numSamples (c.channel().ySampling, minY, maxY); - cd.ys = c.channel().ySampling; + cd.nx = numSamples (c.channel().xSampling, minX, maxX); + cd.ny = numSamples (c.channel().ySampling, minY, maxY); + cd.ys = c.channel().ySampling; - cd.size = pixelTypeSize (c.channel().type) / pixelTypeSize (HALF); + cd.size = pixelTypeSize (c.channel().type) / pixelTypeSize (HALF); - tmpBufferEnd += cd.nx * cd.ny * cd.size; + tmpBufferEnd += cd.nx * cd.ny * cd.size; } if (_format == XDR) { - // - // Machine-independent (Xdr) data format - // - - for (int y = minY; y <= maxY; ++y) - { - for (int i = 0; i < _numChans; ++i) - { - ChannelData &cd = _channelData[i]; - - if (modp (y, cd.ys) != 0) - continue; - - for (int x = cd.nx * cd.size; x > 0; --x) - { - Xdr::read (inPtr, *cd.end); - ++cd.end; - } - } - } + // + // Machine-independent (Xdr) data format + // + + for (int y = minY; y <= maxY; ++y) + { + for (int i = 0; i < _numChans; ++i) + { + ChannelData &cd = _channelData[i]; + + if (modp (y, cd.ys) != 0) + continue; + + for (int x = cd.nx * cd.size; x > 0; --x) + { + Xdr::read (inPtr, *cd.end); + ++cd.end; + } + } + } } else { - // - // Native, machine-dependent data format - // - - for (int y = minY; y <= maxY; ++y) - { - for (int i = 0; i < _numChans; ++i) - { - ChannelData &cd = _channelData[i]; - - if (modp (y, cd.ys) != 0) - continue; - - int n = cd.nx * cd.size; - memcpy (cd.end, inPtr, n * sizeof (unsigned short)); - inPtr += n * sizeof (unsigned short); - cd.end += n; - } - } + // + // Native, machine-dependent data format + // + + for (int y = minY; y <= maxY; ++y) + { + for (int i = 0; i < _numChans; ++i) + { + ChannelData &cd = _channelData[i]; + + if (modp (y, cd.ys) != 0) + continue; + + int n = cd.nx * cd.size; + memcpy (cd.end, inPtr, n * sizeof (unsigned short)); + inPtr += n * sizeof (unsigned short); + cd.end += n; + } + } } #if defined (DEBUG) - for (int i = 1; i < _numChans; ++i) - assert (_channelData[i-1].end == _channelData[i].start); + for (int i = 1; i < _numChans; ++i) + assert (_channelData[i-1].end == _channelData[i].start); - assert (_channelData[_numChans-1].end == tmpBufferEnd); + assert (_channelData[_numChans-1].end == tmpBufferEnd); #endif @@ -425,9 +426,9 @@ PizCompressor::compress (const char *inPtr, unsigned short maxNonZero; bitmapFromData (_tmpBuffer, - tmpBufferEnd - _tmpBuffer, - bitmap, - minNonZero, maxNonZero); + tmpBufferEnd - _tmpBuffer, + bitmap, + minNonZero, maxNonZero); AutoArray lut; unsigned short maxValue = forwardLutFromBitmap (bitmap, lut); @@ -444,8 +445,8 @@ PizCompressor::compress (const char *inPtr, if (minNonZero <= maxNonZero) { - Xdr::write (buf, (char *) &bitmap[0] + minNonZero, - maxNonZero - minNonZero + 1); + Xdr::write (buf, (char *) &bitmap[0] + minNonZero, + maxNonZero - minNonZero + 1); } // @@ -454,15 +455,15 @@ PizCompressor::compress (const char *inPtr, for (int i = 0; i < _numChans; ++i) { - ChannelData &cd = _channelData[i]; - - for (int j = 0; j < cd.size; ++j) - { - wav2Encode (cd.start + j, - cd.nx, cd.size, - cd.ny, cd.nx * cd.size, - maxValue); - } + ChannelData &cd = _channelData[i]; + + for (int j = 0; j < cd.size; ++j) + { + wav2Encode (cd.start + j, + cd.nx, cd.size, + cd.ny, cd.nx * cd.size, + maxValue); + } } // @@ -482,23 +483,23 @@ PizCompressor::compress (const char *inPtr, int PizCompressor::uncompress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr) + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr) { // // This is the cunompress function which is used by both the tiled and // scanline decompression routines. // - + // // Special case - empty input buffer // if (inSize == 0) { - outPtr = _outBuffer; - return 0; + outPtr = _outBuffer; + return 0; } // @@ -509,10 +510,10 @@ PizCompressor::uncompress (const char *inPtr, int maxX = range.max.x; int minY = range.min.y; int maxY = range.max.y; - + if (maxY > _maxY) maxY = _maxY; - + if (maxX > _maxX) maxX = _maxX; @@ -520,21 +521,21 @@ PizCompressor::uncompress (const char *inPtr, int i = 0; for (ChannelList::ConstIterator c = _channels.begin(); - c != _channels.end(); - ++c, ++i) + c != _channels.end(); + ++c, ++i) { - ChannelData &cd = _channelData[i]; + ChannelData &cd = _channelData[i]; - cd.start = tmpBufferEnd; - cd.end = cd.start; + cd.start = tmpBufferEnd; + cd.end = cd.start; - cd.nx = numSamples (c.channel().xSampling, minX, maxX); - cd.ny = numSamples (c.channel().ySampling, minY, maxY); - cd.ys = c.channel().ySampling; + cd.nx = numSamples (c.channel().xSampling, minX, maxX); + cd.ny = numSamples (c.channel().ySampling, minY, maxY); + cd.ys = c.channel().ySampling; - cd.size = pixelTypeSize (c.channel().type) / pixelTypeSize (HALF); + cd.size = pixelTypeSize (c.channel().type) / pixelTypeSize (HALF); - tmpBufferEnd += cd.nx * cd.ny * cd.size; + tmpBufferEnd += cd.nx * cd.ny * cd.size; } // @@ -552,14 +553,14 @@ PizCompressor::uncompress (const char *inPtr, if (maxNonZero >= BITMAP_SIZE) { - throw InputExc ("Error in header for PIZ-compressed data " - "(invalid bitmap size)."); + throw InputExc ("Error in header for PIZ-compressed data " + "(invalid bitmap size)."); } if (minNonZero <= maxNonZero) { - Xdr::read (inPtr, (char *) &bitmap[0] + minNonZero, - maxNonZero - minNonZero + 1); + Xdr::read (inPtr, (char *) &bitmap[0] + minNonZero, + maxNonZero - minNonZero + 1); } AutoArray lut; @@ -572,6 +573,12 @@ PizCompressor::uncompress (const char *inPtr, int length; Xdr::read (inPtr, length); + if (length > inSize) + { + throw InputExc ("Error in header for PIZ-compressed data " + "(invalid array length)."); + } + hufUncompress (inPtr, length, _tmpBuffer, tmpBufferEnd - _tmpBuffer); // @@ -580,15 +587,15 @@ PizCompressor::uncompress (const char *inPtr, for (int i = 0; i < _numChans; ++i) { - ChannelData &cd = _channelData[i]; - - for (int j = 0; j < cd.size; ++j) - { - wav2Decode (cd.start + j, - cd.nx, cd.size, - cd.ny, cd.nx * cd.size, - maxValue); - } + ChannelData &cd = _channelData[i]; + + for (int j = 0; j < cd.size; ++j) + { + wav2Decode (cd.start + j, + cd.nx, cd.size, + cd.ny, cd.nx * cd.size, + maxValue); + } } // @@ -596,7 +603,7 @@ PizCompressor::uncompress (const char *inPtr, // applyLut (lut, _tmpBuffer, tmpBufferEnd - _tmpBuffer); - + // // Rearrange the pixel data into the format expected by the caller. // @@ -605,56 +612,56 @@ PizCompressor::uncompress (const char *inPtr, if (_format == XDR) { - // - // Machine-independent (Xdr) data format - // - - for (int y = minY; y <= maxY; ++y) - { - for (int i = 0; i < _numChans; ++i) - { - ChannelData &cd = _channelData[i]; - - if (modp (y, cd.ys) != 0) - continue; - - for (int x = cd.nx * cd.size; x > 0; --x) - { - Xdr::write (outEnd, *cd.end); - ++cd.end; - } - } - } + // + // Machine-independent (Xdr) data format + // + + for (int y = minY; y <= maxY; ++y) + { + for (int i = 0; i < _numChans; ++i) + { + ChannelData &cd = _channelData[i]; + + if (modp (y, cd.ys) != 0) + continue; + + for (int x = cd.nx * cd.size; x > 0; --x) + { + Xdr::write (outEnd, *cd.end); + ++cd.end; + } + } + } } else { - // - // Native, machine-dependent data format - // - - for (int y = minY; y <= maxY; ++y) - { - for (int i = 0; i < _numChans; ++i) - { - ChannelData &cd = _channelData[i]; - - if (modp (y, cd.ys) != 0) - continue; - - int n = cd.nx * cd.size; - memcpy (outEnd, cd.end, n * sizeof (unsigned short)); - outEnd += n * sizeof (unsigned short); - cd.end += n; - } - } + // + // Native, machine-dependent data format + // + + for (int y = minY; y <= maxY; ++y) + { + for (int i = 0; i < _numChans; ++i) + { + ChannelData &cd = _channelData[i]; + + if (modp (y, cd.ys) != 0) + continue; + + int n = cd.nx * cd.size; + memcpy (outEnd, cd.end, n * sizeof (unsigned short)); + outEnd += n * sizeof (unsigned short); + cd.end += n; + } + } } #if defined (DEBUG) - for (int i = 1; i < _numChans; ++i) - assert (_channelData[i-1].end == _channelData[i].start); + for (int i = 1; i < _numChans; ++i) + assert (_channelData[i-1].end == _channelData[i].start); - assert (_channelData[_numChans-1].end == tmpBufferEnd); + assert (_channelData[_numChans-1].end == tmpBufferEnd); #endif @@ -663,4 +670,4 @@ PizCompressor::uncompress (const char *inPtr, } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfPizCompressor.h b/3rdparty/openexr/IlmImf/ImfPizCompressor.h index df7de7c258..703f55214c 100644 --- a/3rdparty/openexr/IlmImf/ImfPizCompressor.h +++ b/3rdparty/openexr/IlmImf/ImfPizCompressor.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,59 +42,69 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfCompressor.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" -namespace Imf { -class ChannelList; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class PizCompressor: public Compressor { public: + IMF_EXPORT PizCompressor (const Header &hdr, size_t maxScanLineSize, size_t numScanLines); + IMF_EXPORT virtual ~PizCompressor (); + IMF_EXPORT virtual int numScanLines () const; + IMF_EXPORT virtual Format format () const; + IMF_EXPORT virtual int compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); - + int inSize, + int minY, + const char *&outPtr); + + IMF_EXPORT virtual int compressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + IMF_EXPORT virtual int uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); - + int inSize, + int minY, + const char *&outPtr); + + IMF_EXPORT virtual int uncompressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); private: struct ChannelData; - + int compress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); - + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + int uncompress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); int _maxScanLineSize; Format _format; @@ -110,6 +120,6 @@ class PizCompressor: public Compressor }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfPreviewImage.cpp b/3rdparty/openexr/IlmImf/ImfPreviewImage.cpp index 5bd1e403a9..8027d0f3c3 100644 --- a/3rdparty/openexr/IlmImf/ImfPreviewImage.cpp +++ b/3rdparty/openexr/IlmImf/ImfPreviewImage.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2003, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,16 +39,17 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfPreviewImage.h" +#include "ImfCheckedArithmetic.h" #include "Iex.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER PreviewImage::PreviewImage (unsigned int width, - unsigned int height, - const PreviewRgba pixels[]) + unsigned int height, + const PreviewRgba pixels[]) { _width = width; _height = height; @@ -57,13 +58,13 @@ PreviewImage::PreviewImage (unsigned int width, if (pixels) { - for (unsigned int i = 0; i < _width * _height; ++i) - _pixels[i] = pixels[i]; + for (unsigned int i = 0; i < _width * _height; ++i) + _pixels[i] = pixels[i]; } else { - for (unsigned int i = 0; i < _width * _height; ++i) - _pixels[i] = PreviewRgba(); + for (unsigned int i = 0; i < _width * _height; ++i) + _pixels[i] = PreviewRgba(); } } @@ -74,7 +75,7 @@ PreviewImage::PreviewImage (const PreviewImage &other): _pixels (new PreviewRgba [other._width * other._height]) { for (unsigned int i = 0; i < _width * _height; ++i) - _pixels[i] = other._pixels[i]; + _pixels[i] = other._pixels[i]; } @@ -94,10 +95,10 @@ PreviewImage::operator = (const PreviewImage &other) _pixels = new PreviewRgba [other._width * other._height]; for (unsigned int i = 0; i < _width * _height; ++i) - _pixels[i] = other._pixels[i]; + _pixels[i] = other._pixels[i]; return *this; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfPreviewImage.h b/3rdparty/openexr/IlmImf/ImfPreviewImage.h index 716085c8df..20a2253c34 100644 --- a/3rdparty/openexr/IlmImf/ImfPreviewImage.h +++ b/3rdparty/openexr/IlmImf/ImfPreviewImage.h @@ -2,9 +2,9 @@ // // Copyright (c) 2003, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -36,6 +36,9 @@ #ifndef INCLUDED_IMF_PREVIEW_IMAGE_H #define INCLUDED_IMF_PREVIEW_IMAGE_H +#include "ImfNamespace.h" +#include "ImfExport.h" + //----------------------------------------------------------------------------- // // class PreviewImage -- a usually small, low-dynamic range image, @@ -45,7 +48,8 @@ // //----------------------------------------------------------------------------- -namespace Imf { + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER struct PreviewRgba @@ -53,16 +57,16 @@ struct PreviewRgba unsigned char r; // Red, green and blue components of unsigned char g; // the pixel's color; intensity is unsigned char b; // proportional to pow (x/255, 2.2), - // where x is r, g, or b. + // where x is r, g, or b. unsigned char a; // The pixel's alpha; 0 == transparent, - // 255 == opaque. + // 255 == opaque. PreviewRgba (unsigned char r = 0, - unsigned char g = 0, - unsigned char b = 0, - unsigned char a = 255) - : r(r), g(g), b(b), a(a) {} + unsigned char g = 0, + unsigned char b = 0, + unsigned char a = 255) + : r(r), g(g), b(b), a(a) {} }; @@ -82,18 +86,22 @@ class PreviewImage // (r = 0, b = 0, g = 0, a = 255). // //-------------------------------------------------------------------- - + + IMF_EXPORT PreviewImage (unsigned int width = 0, - unsigned int height = 0, - const PreviewRgba pixels[] = 0); + unsigned int height = 0, + const PreviewRgba pixels[] = 0); //----------------------------------------------------- // Copy constructor, destructor and assignment operator //----------------------------------------------------- + IMF_EXPORT PreviewImage (const PreviewImage &other); + IMF_EXPORT ~PreviewImage (); + IMF_EXPORT PreviewImage & operator = (const PreviewImage &other); @@ -101,10 +109,14 @@ class PreviewImage // Access to width, height and to the pixel array //----------------------------------------------- + IMF_EXPORT unsigned int width () const {return _width;} + IMF_EXPORT unsigned int height () const {return _height;} + IMF_EXPORT PreviewRgba * pixels () {return _pixels;} + IMF_EXPORT const PreviewRgba * pixels () const {return _pixels;} @@ -112,11 +124,13 @@ class PreviewImage // Access to individual pixels //---------------------------- + IMF_EXPORT PreviewRgba & pixel (unsigned int x, unsigned int y) - {return _pixels[y * _width + x];} + {return _pixels[y * _width + x];} + IMF_EXPORT const PreviewRgba & pixel (unsigned int x, unsigned int y) const - {return _pixels[y * _width + x];} + {return _pixels[y * _width + x];} private: @@ -126,6 +140,6 @@ class PreviewImage }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfPreviewImageAttribute.cpp b/3rdparty/openexr/IlmImf/ImfPreviewImageAttribute.cpp index 441ee228e8..8729f88eaa 100644 --- a/3rdparty/openexr/IlmImf/ImfPreviewImageAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfPreviewImageAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,8 +42,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -55,7 +56,7 @@ PreviewImageAttribute::staticTypeName () template <> void -PreviewImageAttribute::writeValueTo (OStream &os, int) const +PreviewImageAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.width()); Xdr::write (os, _value.height()); @@ -65,17 +66,17 @@ PreviewImageAttribute::writeValueTo (OStream &os, int) const for (int i = 0; i < numPixels; ++i) { - Xdr::write (os, pixels[i].r); - Xdr::write (os, pixels[i].g); - Xdr::write (os, pixels[i].b); - Xdr::write (os, pixels[i].a); + Xdr::write (os, pixels[i].r); + Xdr::write (os, pixels[i].g); + Xdr::write (os, pixels[i].b); + Xdr::write (os, pixels[i].a); } } template <> void -PreviewImageAttribute::readValueFrom (IStream &is, int, int) +PreviewImageAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { int width, height; @@ -89,14 +90,14 @@ PreviewImageAttribute::readValueFrom (IStream &is, int, int) for (int i = 0; i < numPixels; ++i) { - Xdr::read (is, pixels[i].r); - Xdr::read (is, pixels[i].g); - Xdr::read (is, pixels[i].b); - Xdr::read (is, pixels[i].a); + Xdr::read (is, pixels[i].r); + Xdr::read (is, pixels[i].g); + Xdr::read (is, pixels[i].b); + Xdr::read (is, pixels[i].a); } _value = p; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfPreviewImageAttribute.h b/3rdparty/openexr/IlmImf/ImfPreviewImageAttribute.h index bd80dbf411..160e409551 100644 --- a/3rdparty/openexr/IlmImf/ImfPreviewImageAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfPreviewImageAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,30 +42,29 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfPreviewImage.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { - -typedef TypedAttribute PreviewImageAttribute; +typedef TypedAttribute PreviewImageAttribute; template <> +IMF_EXPORT const char *PreviewImageAttribute::staticTypeName (); template <> -void PreviewImageAttribute::writeValueTo (OStream &, int) const; +IMF_EXPORT +void PreviewImageAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; template <> -void PreviewImageAttribute::readValueFrom (IStream &, int, int); - +IMF_EXPORT +void PreviewImageAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); -} // namespace Imf -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfPxr24Compressor.cpp b/3rdparty/openexr/IlmImf/ImfPxr24Compressor.cpp index f9f35d3cd7..6489576ad5 100644 --- a/3rdparty/openexr/IlmImf/ImfPxr24Compressor.cpp +++ b/3rdparty/openexr/IlmImf/ImfPxr24Compressor.cpp @@ -62,24 +62,27 @@ // string of bytes is compressed with zlib. // //----------------------------------------------------------------------------- -//#define ZLIB_WINAPI -#include -#include -#include -#include -#include +#include "ImfPxr24Compressor.h" +#include "ImfHeader.h" +#include "ImfChannelList.h" +#include "ImfMisc.h" +#include "ImfCheckedArithmetic.h" +#include "ImfNamespace.h" + #include #include + #include #include #include #include using namespace std; -using namespace Imath; +using namespace IMATH_NAMESPACE; + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { namespace { // @@ -92,8 +95,8 @@ floatToFloat24 (float f) { union { - float f; - unsigned int i; + float f; + unsigned int i; } u; u.f = f; @@ -110,48 +113,48 @@ floatToFloat24 (float f) if (e == 0x7f800000) { - if (m) - { - // - // F is a NAN; we preserve the sign bit and - // the 15 leftmost bits of the significand, - // with one exception: If the 15 leftmost - // bits are all zero, the NAN would turn - // into an infinity, so we have to set at - // least one bit in the significand. - // - - m >>= 8; - i = (e >> 8) | m | (m == 0); + if (m) + { + // + // F is a NAN; we preserve the sign bit and + // the 15 leftmost bits of the significand, + // with one exception: If the 15 leftmost + // bits are all zero, the NAN would turn + // into an infinity, so we have to set at + // least one bit in the significand. + // + + m >>= 8; + i = (e >> 8) | m | (m == 0); + } + else + { + // + // F is an infinity. + // + + i = e >> 8; + } } else { - // - // F is an infinity. - // - - i = e >> 8; - } - } - else - { - // - // F is finite, round the significand to 15 bits. - // - - i = ((e | m) + (m & 0x00000080)) >> 8; - - if (i >= 0x7f8000) - { - // - // F was close to FLT_MAX, and the significand was - // rounded up, resulting in an exponent overflow. - // Avoid the overflow by truncating the significand - // instead of rounding it. - // - - i = (e | m) >> 8; - } + // + // F is finite, round the significand to 15 bits. + // + + i = ((e | m) + (m & 0x00000080)) >> 8; + + if (i >= 0x7f8000) + { + // + // F was close to FLT_MAX, and the significand was + // rounded up, resulting in an exponent overflow. + // Avoid the overflow by truncating the significand + // instead of rounding it. + // + + i = (e | m) >> 8; + } } return (s >> 8) | i; @@ -161,24 +164,24 @@ floatToFloat24 (float f) void notEnoughData () { - throw Iex::InputExc ("Error decompressing data " - "(input data are shorter than expected)."); + throw IEX_NAMESPACE::InputExc ("Error decompressing data " + "(input data are shorter than expected)."); } void tooMuchData () { - throw Iex::InputExc ("Error decompressing data " - "(input data are longer than expected)."); + throw IEX_NAMESPACE::InputExc ("Error decompressing data " + "(input data are longer than expected)."); } } // namespace Pxr24Compressor::Pxr24Compressor (const Header &hdr, - size_t maxScanLineSize, - size_t numScanLines) + size_t maxScanLineSize, + size_t numScanLines) : Compressor (hdr), _maxScanLineSize (maxScanLineSize), @@ -229,23 +232,23 @@ Pxr24Compressor::format () const int Pxr24Compressor::compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { return compress (inPtr, - inSize, - Box2i (V2i (_minX, minY), - V2i (_maxX, minY + _numScanLines - 1)), - outPtr); + inSize, + Box2i (V2i (_minX, minY), + V2i (_maxX, minY + _numScanLines - 1)), + outPtr); } - + int Pxr24Compressor::compressTile (const char *inPtr, - int inSize, - Box2i range, - const char *&outPtr) + int inSize, + Box2i range, + const char *&outPtr) { return compress (inPtr, inSize, range, outPtr); } @@ -253,23 +256,23 @@ Pxr24Compressor::compressTile (const char *inPtr, int Pxr24Compressor::uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { return uncompress (inPtr, - inSize, - Box2i (V2i (_minX, minY), - V2i (_maxX, minY + _numScanLines - 1)), - outPtr); + inSize, + Box2i (V2i (_minX, minY), + V2i (_maxX, minY + _numScanLines - 1)), + outPtr); } - + int Pxr24Compressor::uncompressTile (const char *inPtr, - int inSize, - Box2i range, - const char *&outPtr) + int inSize, + Box2i range, + const char *&outPtr) { return uncompress (inPtr, inSize, range, outPtr); } @@ -277,14 +280,14 @@ Pxr24Compressor::uncompressTile (const char *inPtr, int Pxr24Compressor::compress (const char *inPtr, - int inSize, - Box2i range, - const char *&outPtr) + int inSize, + Box2i range, + const char *&outPtr) { if (inSize == 0) { - outPtr = _outBuffer; - return 0; + outPtr = _outBuffer; + return 0; } int minX = range.min.x; @@ -296,139 +299,139 @@ Pxr24Compressor::compress (const char *inPtr, for (int y = minY; y <= maxY; ++y) { - for (ChannelList::ConstIterator i = _channels.begin(); - i != _channels.end(); - ++i) - { - const Channel &c = i.channel(); + for (ChannelList::ConstIterator i = _channels.begin(); + i != _channels.end(); + ++i) + { + const Channel &c = i.channel(); - if (modp (y, c.ySampling) != 0) - continue; + if (modp (y, c.ySampling) != 0) + continue; - int n = numSamples (c.xSampling, minX, maxX); + int n = numSamples (c.xSampling, minX, maxX); - unsigned char *ptr[4]; - unsigned int previousPixel = 0; + unsigned char *ptr[4]; + unsigned int previousPixel = 0; - switch (c.type) - { - case UINT: + switch (c.type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: - ptr[0] = tmpBufferEnd; - ptr[1] = ptr[0] + n; - ptr[2] = ptr[1] + n; - ptr[3] = ptr[2] + n; - tmpBufferEnd = ptr[3] + n; + ptr[0] = tmpBufferEnd; + ptr[1] = ptr[0] + n; + ptr[2] = ptr[1] + n; + ptr[3] = ptr[2] + n; + tmpBufferEnd = ptr[3] + n; - for (int j = 0; j < n; ++j) - { - unsigned int pixel; - char *pPtr = (char *) &pixel; + for (int j = 0; j < n; ++j) + { + unsigned int pixel; + char *pPtr = (char *) &pixel; - for (int k = 0; k < sizeof (pixel); ++k) - *pPtr++ = *inPtr++; + for (size_t k = 0; k < sizeof (pixel); ++k) + *pPtr++ = *inPtr++; - unsigned int diff = pixel - previousPixel; - previousPixel = pixel; + unsigned int diff = pixel - previousPixel; + previousPixel = pixel; - *(ptr[0]++) = diff >> 24; - *(ptr[1]++) = diff >> 16; - *(ptr[2]++) = diff >> 8; - *(ptr[3]++) = diff; - } + *(ptr[0]++) = diff >> 24; + *(ptr[1]++) = diff >> 16; + *(ptr[2]++) = diff >> 8; + *(ptr[3]++) = diff; + } - break; + break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: - ptr[0] = tmpBufferEnd; - ptr[1] = ptr[0] + n; - tmpBufferEnd = ptr[1] + n; + ptr[0] = tmpBufferEnd; + ptr[1] = ptr[0] + n; + tmpBufferEnd = ptr[1] + n; - for (int j = 0; j < n; ++j) - { - half pixel; + for (int j = 0; j < n; ++j) + { + half pixel; - pixel = *(const half *) inPtr; - inPtr += sizeof (half); + pixel = *(const half *) inPtr; + inPtr += sizeof (half); - unsigned int diff = pixel.bits() - previousPixel; - previousPixel = pixel.bits(); + unsigned int diff = pixel.bits() - previousPixel; + previousPixel = pixel.bits(); - *(ptr[0]++) = diff >> 8; - *(ptr[1]++) = diff; - } + *(ptr[0]++) = diff >> 8; + *(ptr[1]++) = diff; + } - break; + break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: - ptr[0] = tmpBufferEnd; - ptr[1] = ptr[0] + n; - ptr[2] = ptr[1] + n; - tmpBufferEnd = ptr[2] + n; + ptr[0] = tmpBufferEnd; + ptr[1] = ptr[0] + n; + ptr[2] = ptr[1] + n; + tmpBufferEnd = ptr[2] + n; - for (int j = 0; j < n; ++j) - { - float pixel; - char *pPtr = (char *) &pixel; + for (int j = 0; j < n; ++j) + { + float pixel; + char *pPtr = (char *) &pixel; - for (int k = 0; k < sizeof (pixel); ++k) - *pPtr++ = *inPtr++; + for (size_t k = 0; k < sizeof (pixel); ++k) + *pPtr++ = *inPtr++; - unsigned int pixel24 = floatToFloat24 (pixel); - unsigned int diff = pixel24 - previousPixel; - previousPixel = pixel24; + unsigned int pixel24 = floatToFloat24 (pixel); + unsigned int diff = pixel24 - previousPixel; + previousPixel = pixel24; - *(ptr[0]++) = diff >> 16; - *(ptr[1]++) = diff >> 8; - *(ptr[2]++) = diff; - } + *(ptr[0]++) = diff >> 16; + *(ptr[1]++) = diff >> 8; + *(ptr[2]++) = diff; + } - break; + break; - default: + default: - assert (false); - } - } + assert (false); + } + } } uLongf outSize = int (ceil ((tmpBufferEnd - _tmpBuffer) * 1.01)) + 100; if (Z_OK != ::compress ((Bytef *) _outBuffer, - &outSize, - (const Bytef *) _tmpBuffer, - tmpBufferEnd - _tmpBuffer)) + &outSize, + (const Bytef *) _tmpBuffer, + tmpBufferEnd - _tmpBuffer)) { - throw Iex::BaseExc ("Data compression (zlib) failed."); + throw IEX_NAMESPACE::BaseExc ("Data compression (zlib) failed."); } outPtr = _outBuffer; return outSize; } - -int + +int Pxr24Compressor::uncompress (const char *inPtr, - int inSize, - Box2i range, - const char *&outPtr) + int inSize, + Box2i range, + const char *&outPtr) { if (inSize == 0) { - outPtr = _outBuffer; - return 0; + outPtr = _outBuffer; + return 0; } uLongf tmpSize = _maxScanLineSize * _numScanLines; if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer, - &tmpSize, - (const Bytef *) inPtr, - inSize)) + &tmpSize, + (const Bytef *) inPtr, + inSize)) { - throw Iex::InputExc ("Data decompression (zlib) failed."); + throw IEX_NAMESPACE::InputExc ("Data decompression (zlib) failed."); } int minX = range.min.x; @@ -441,110 +444,110 @@ Pxr24Compressor::uncompress (const char *inPtr, for (int y = minY; y <= maxY; ++y) { - for (ChannelList::ConstIterator i = _channels.begin(); - i != _channels.end(); - ++i) - { - const Channel &c = i.channel(); + for (ChannelList::ConstIterator i = _channels.begin(); + i != _channels.end(); + ++i) + { + const Channel &c = i.channel(); - if (modp (y, c.ySampling) != 0) - continue; + if (modp (y, c.ySampling) != 0) + continue; - int n = numSamples (c.xSampling, minX, maxX); + int n = numSamples (c.xSampling, minX, maxX); - const unsigned char *ptr[4]; - unsigned int pixel = 0; + const unsigned char *ptr[4]; + unsigned int pixel = 0; - switch (c.type) - { - case UINT: + switch (c.type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: - ptr[0] = tmpBufferEnd; - ptr[1] = ptr[0] + n; - ptr[2] = ptr[1] + n; - ptr[3] = ptr[2] + n; - tmpBufferEnd = ptr[3] + n; + ptr[0] = tmpBufferEnd; + ptr[1] = ptr[0] + n; + ptr[2] = ptr[1] + n; + ptr[3] = ptr[2] + n; + tmpBufferEnd = ptr[3] + n; - if (tmpBufferEnd - _tmpBuffer > tmpSize) - notEnoughData(); + if ( (uLongf)(tmpBufferEnd - _tmpBuffer) > tmpSize) + notEnoughData(); - for (int j = 0; j < n; ++j) - { - unsigned int diff = (*(ptr[0]++) << 24) | - (*(ptr[1]++) << 16) | - (*(ptr[2]++) << 8) | - *(ptr[3]++); + for (int j = 0; j < n; ++j) + { + unsigned int diff = (*(ptr[0]++) << 24) | + (*(ptr[1]++) << 16) | + (*(ptr[2]++) << 8) | + *(ptr[3]++); - pixel += diff; + pixel += diff; - char *pPtr = (char *) &pixel; + char *pPtr = (char *) &pixel; - for (int k = 0; k < sizeof (pixel); ++k) - *writePtr++ = *pPtr++; - } + for (size_t k = 0; k < sizeof (pixel); ++k) + *writePtr++ = *pPtr++; + } - break; + break; - case HALF: + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: - ptr[0] = tmpBufferEnd; - ptr[1] = ptr[0] + n; - tmpBufferEnd = ptr[1] + n; + ptr[0] = tmpBufferEnd; + ptr[1] = ptr[0] + n; + tmpBufferEnd = ptr[1] + n; - if (tmpBufferEnd - _tmpBuffer > tmpSize) - notEnoughData(); + if ( (uLongf)(tmpBufferEnd - _tmpBuffer) > tmpSize) + notEnoughData(); - for (int j = 0; j < n; ++j) - { - unsigned int diff = (*(ptr[0]++) << 8) | - *(ptr[1]++); + for (int j = 0; j < n; ++j) + { + unsigned int diff = (*(ptr[0]++) << 8) | + *(ptr[1]++); - pixel += diff; + pixel += diff; - half * hPtr = (half *) writePtr; - hPtr->setBits ((unsigned short) pixel); - writePtr += sizeof (half); - } + half * hPtr = (half *) writePtr; + hPtr->setBits ((unsigned short) pixel); + writePtr += sizeof (half); + } - break; + break; - case FLOAT: + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: - ptr[0] = tmpBufferEnd; - ptr[1] = ptr[0] + n; - ptr[2] = ptr[1] + n; - tmpBufferEnd = ptr[2] + n; + ptr[0] = tmpBufferEnd; + ptr[1] = ptr[0] + n; + ptr[2] = ptr[1] + n; + tmpBufferEnd = ptr[2] + n; - if (tmpBufferEnd - _tmpBuffer > tmpSize) - notEnoughData(); + if ( (uLongf) (tmpBufferEnd - _tmpBuffer) > tmpSize) + notEnoughData(); - for (int j = 0; j < n; ++j) - { - unsigned int diff = (*(ptr[0]++) << 24) | - (*(ptr[1]++) << 16) | - (*(ptr[2]++) << 8); - pixel += diff; + for (int j = 0; j < n; ++j) + { + unsigned int diff = (*(ptr[0]++) << 24) | + (*(ptr[1]++) << 16) | + (*(ptr[2]++) << 8); + pixel += diff; - char *pPtr = (char *) &pixel; + char *pPtr = (char *) &pixel; - for (int k = 0; k < sizeof (pixel); ++k) - *writePtr++ = *pPtr++; - } + for (size_t k = 0; k < sizeof (pixel); ++k) + *writePtr++ = *pPtr++; + } - break; + break; - default: + default: - assert (false); - } - } + assert (false); + } + } } - if (tmpBufferEnd - _tmpBuffer < tmpSize) - tooMuchData(); + if ((uLongf) (tmpBufferEnd - _tmpBuffer) < tmpSize) + tooMuchData(); outPtr = _outBuffer; return writePtr - _outBuffer; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfPxr24Compressor.h b/3rdparty/openexr/IlmImf/ImfPxr24Compressor.h index b94cbdce91..d8c7091c33 100644 --- a/3rdparty/openexr/IlmImf/ImfPxr24Compressor.h +++ b/3rdparty/openexr/IlmImf/ImfPxr24Compressor.h @@ -40,57 +40,66 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfCompressor.h" +#include "ImfNamespace.h" +#include "ImfExport.h" +#include "ImfForward.h" -namespace Imf { - -class ChannelList; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class Pxr24Compressor: public Compressor { public: - Pxr24Compressor (const Header &hdr, + IMF_EXPORT + Pxr24Compressor (const Header &hdr, size_t maxScanLineSize, size_t numScanLines); + IMF_EXPORT virtual ~Pxr24Compressor (); + IMF_EXPORT virtual int numScanLines () const; + IMF_EXPORT virtual Format format () const; + IMF_EXPORT virtual int compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); - + int inSize, + int minY, + const char *&outPtr); + + IMF_EXPORT virtual int compressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + IMF_EXPORT virtual int uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); - + int inSize, + int minY, + const char *&outPtr); + + IMF_EXPORT virtual int uncompressTile (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); private: int compress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); - + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); + int uncompress (const char *inPtr, - int inSize, - Imath::Box2i range, - const char *&outPtr); + int inSize, + IMATH_NAMESPACE::Box2i range, + const char *&outPtr); int _maxScanLineSize; int _numScanLines; @@ -103,6 +112,6 @@ class Pxr24Compressor: public Compressor }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfRational.cpp b/3rdparty/openexr/IlmImf/ImfRational.cpp index 7eff9e2105..fda7fc937a 100644 --- a/3rdparty/openexr/IlmImf/ImfRational.cpp +++ b/3rdparty/openexr/IlmImf/ImfRational.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,8 +45,10 @@ #include using namespace std; +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { namespace { double @@ -72,8 +74,8 @@ denom (double x, double e) } else { - double r = frac (1 / x, e); - + double r = frac (1 / x, e); + if (e > r) { return floor (1 / x + e); @@ -95,25 +97,25 @@ Rational::Rational (double x) if (x >= 0) { - sign = 1; // positive + sign = 1; // positive } else if (x < 0) { - sign = -1; // negative - x = -x; + sign = -1; // negative + x = -x; } else { - n = 0; // NaN - d = 0; - return; + n = 0; // NaN + d = 0; + return; } if (x >= (1U << 31) - 0.5) { - n = sign; // infinity - d = 0; - return; + n = sign; // infinity + d = 0; + return; } double e = (x < 1? 1: x) / (1U << 30); @@ -122,4 +124,4 @@ Rational::Rational (double x) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfRational.h b/3rdparty/openexr/IlmImf/ImfRational.h index a2493b1c86..9dfe806a94 100644 --- a/3rdparty/openexr/IlmImf/ImfRational.h +++ b/3rdparty/openexr/IlmImf/ImfRational.h @@ -2,9 +2,9 @@ // // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -36,13 +36,16 @@ #ifndef INCLUDED_IMF_RATIONAL_H #define INCLUDED_IMF_RATIONAL_H +#include "ImfExport.h" +#include "ImfNamespace.h" + //----------------------------------------------------------------------------- // // Rational numbers // // A rational number is represented as pair of integers, n and d. // The value of of the rational number is -// +// // n/d for d > 0 // positive infinity for n > 0, d == 0 // negative infinity for n < 0, d == 0 @@ -50,7 +53,8 @@ // //----------------------------------------------------------------------------- -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + class Rational { @@ -71,13 +75,14 @@ class Rational // Constructor, explicitly sets n and d //------------------------------------- - Rational (int _n, int _d): n (_n), d (_d) {} + Rational (int n, int d): n (n), d (d) {} //---------------------------- // Constructor, approximates x //---------------------------- + IMF_EXPORT explicit Rational (double x); @@ -88,6 +93,7 @@ class Rational operator double () const {return double (n) / double (d);} }; -} // namespace Imf + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfRationalAttribute.cpp b/3rdparty/openexr/IlmImf/ImfRationalAttribute.cpp index 0a7afca060..a41646832b 100644 --- a/3rdparty/openexr/IlmImf/ImfRationalAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfRationalAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,8 +41,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -54,7 +55,7 @@ RationalAttribute::staticTypeName () template <> void -RationalAttribute::writeValueTo (OStream &os, int) const +RationalAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.n); Xdr::write (os, _value.d); @@ -63,11 +64,11 @@ RationalAttribute::writeValueTo (OStream &os, int) const template <> void -RationalAttribute::readValueFrom (IStream &is, int, int) +RationalAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.n); Xdr::read (is, _value.d); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfRationalAttribute.h b/3rdparty/openexr/IlmImf/ImfRationalAttribute.h index cda28619ed..988fe01ab4 100644 --- a/3rdparty/openexr/IlmImf/ImfRationalAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfRationalAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,30 +41,29 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfRational.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { - -typedef TypedAttribute RationalAttribute; +typedef TypedAttribute RationalAttribute; template <> +IMF_EXPORT const char *RationalAttribute::staticTypeName (); template <> -void RationalAttribute::writeValueTo (OStream &, int) const; +IMF_EXPORT +void RationalAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; template <> -void RationalAttribute::readValueFrom (IStream &, int, int); - +IMF_EXPORT +void RationalAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); -} // namespace Imf -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfRgba.h b/3rdparty/openexr/IlmImf/ImfRgba.h index 3f39a115c6..dccba9f0ac 100644 --- a/3rdparty/openexr/IlmImf/ImfRgba.h +++ b/3rdparty/openexr/IlmImf/ImfRgba.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,8 +43,9 @@ //----------------------------------------------------------------------------- #include "half.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER // @@ -57,18 +58,18 @@ struct Rgba half g; half b; half a; - + Rgba () {} Rgba (half r, half g, half b, half a = 1.f): r (r), g (g), b (b), a (a) {} Rgba & operator = (const Rgba &other) { - r = other.r; - g = other.g; - b = other.b; - a = other.a; + r = other.r; + g = other.g; + b = other.b; + a = other.a; - return *this; + return *this; } }; @@ -85,10 +86,10 @@ enum RgbaChannels WRITE_A = 0x08, // Alpha WRITE_Y = 0x10, // Luminance, for black-and-white images, - // or in combination with chroma + // or in combination with chroma WRITE_C = 0x20, // Chroma (two subsampled channels, RY and BY, - // supported only for scanline-based files) + // supported only for scanline-based files) WRITE_RGB = 0x07, // Red, green, blue WRITE_RGBA = 0x0f, // Red, green, blue, alpha @@ -99,6 +100,10 @@ enum RgbaChannels }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfRgbaFile.cpp b/3rdparty/openexr/IlmImf/ImfRgbaFile.cpp index 6b3634eceb..c2b604a196 100644 --- a/3rdparty/openexr/IlmImf/ImfRgbaFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfRgbaFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -51,13 +51,14 @@ #include #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER using namespace std; -using namespace Imath; +using namespace IMATH_NAMESPACE; using namespace RgbaYca; -using namespace IlmThread; +using namespace ILMTHREAD_NAMESPACE; namespace { @@ -68,31 +69,31 @@ insertChannels (Header &header, RgbaChannels rgbaChannels) if (rgbaChannels & (WRITE_Y | WRITE_C)) { - if (rgbaChannels & WRITE_Y) - { - ch.insert ("Y", Channel (HALF, 1, 1)); - } - - if (rgbaChannels & WRITE_C) - { - ch.insert ("RY", Channel (HALF, 2, 2, true)); - ch.insert ("BY", Channel (HALF, 2, 2, true)); - } + if (rgbaChannels & WRITE_Y) + { + ch.insert ("Y", Channel (HALF, 1, 1)); + } + + if (rgbaChannels & WRITE_C) + { + ch.insert ("RY", Channel (HALF, 2, 2, true)); + ch.insert ("BY", Channel (HALF, 2, 2, true)); + } } else { - if (rgbaChannels & WRITE_R) - ch.insert ("R", Channel (HALF, 1, 1)); + if (rgbaChannels & WRITE_R) + ch.insert ("R", Channel (HALF, 1, 1)); - if (rgbaChannels & WRITE_G) - ch.insert ("G", Channel (HALF, 1, 1)); + if (rgbaChannels & WRITE_G) + ch.insert ("G", Channel (HALF, 1, 1)); - if (rgbaChannels & WRITE_B) - ch.insert ("B", Channel (HALF, 1, 1)); + if (rgbaChannels & WRITE_B) + ch.insert ("B", Channel (HALF, 1, 1)); } if (rgbaChannels & WRITE_A) - ch.insert ("A", Channel (HALF, 1, 1)); + ch.insert ("A", Channel (HALF, 1, 1)); header.channels() = ch; } @@ -104,23 +105,23 @@ rgbaChannels (const ChannelList &ch, const string &channelNamePrefix = "") int i = 0; if (ch.findChannel (channelNamePrefix + "R")) - i |= WRITE_R; + i |= WRITE_R; if (ch.findChannel (channelNamePrefix + "G")) - i |= WRITE_G; - + i |= WRITE_G; + if (ch.findChannel (channelNamePrefix + "B")) - i |= WRITE_B; + i |= WRITE_B; if (ch.findChannel (channelNamePrefix + "A")) - i |= WRITE_A; + i |= WRITE_A; if (ch.findChannel (channelNamePrefix + "Y")) - i |= WRITE_Y; + i |= WRITE_Y; if (ch.findChannel (channelNamePrefix + "RY") || - ch.findChannel (channelNamePrefix + "BY")) - i |= WRITE_C; + ch.findChannel (channelNamePrefix + "BY")) + i |= WRITE_C; return RgbaChannels (i); } @@ -130,10 +131,10 @@ string prefixFromLayerName (const string &layerName, const Header &header) { if (layerName.empty()) - return ""; + return ""; if (hasMultiView (header) && multiView(header)[0] == layerName) - return ""; + return ""; return layerName + "."; } @@ -145,7 +146,7 @@ ywFromHeader (const Header &header) Chromaticities cr; if (hasChromaticities (header)) - cr = chromaticities (header); + cr = chromaticities (header); return computeYw (cr); } @@ -173,13 +174,13 @@ cachePadding (ptrdiff_t size) int i = LOG2_CACHE_LINE_SIZE + 2; while ((size >> i) > 1) - ++i; + ++i; if (size > (1 << (i + 1)) - 64) - return 64 + ((1 << (i + 1)) - size); + return 64 + ((1 << (i + 1)) - size); if (size < (1 << i) + 64) - return 64 + ((1 << i) - size); + return 64 + ((1 << i) - size); return 0; } @@ -195,11 +196,11 @@ class RgbaOutputFile::ToYca: public Mutex ~ToYca (); void setYCRounding (unsigned int roundY, - unsigned int roundC); + unsigned int roundC); void setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride); + size_t xStride, + size_t yStride); void writePixels (int numScanLines); int currentScanLine () const; @@ -235,7 +236,7 @@ class RgbaOutputFile::ToYca: public Mutex RgbaOutputFile::ToYca::ToYca (OutputFile &outputFile, - RgbaChannels rgbaChannels) + RgbaChannels rgbaChannels) : _outputFile (outputFile) { @@ -251,11 +252,11 @@ RgbaOutputFile::ToYca::ToYca (OutputFile &outputFile, _linesConverted = 0; _lineOrder = _outputFile.header().lineOrder(); - + if (_lineOrder == INCREASING_Y) - _currentScanLine = dw.min.y; + _currentScanLine = dw.min.y; else - _currentScanLine = dw.max.y; + _currentScanLine = dw.max.y; _yw = ywFromHeader (_outputFile.header()); @@ -264,7 +265,7 @@ RgbaOutputFile::ToYca::ToYca (OutputFile &outputFile, _bufBase = new Rgba[(_width + pad) * N]; for (int i = 0; i < N; ++i) - _buf[i] = _bufBase + (i * (_width + pad)); + _buf[i] = _bufBase + (i * (_width + pad)); _tmpBuf = new Rgba[_width + N - 1]; @@ -286,7 +287,7 @@ RgbaOutputFile::ToYca::~ToYca () void RgbaOutputFile::ToYca::setYCRounding (unsigned int roundY, - unsigned int roundC) + unsigned int roundC) { _roundY = roundY; _roundC = roundC; @@ -295,55 +296,55 @@ RgbaOutputFile::ToYca::setYCRounding (unsigned int roundY, void RgbaOutputFile::ToYca::setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride) + size_t xStride, + size_t yStride) { if (_fbBase == 0) { - FrameBuffer fb; - - if (_writeY) - { - fb.insert ("Y", - Slice (HALF, // type - (char *) &_tmpBuf[-_xMin].g, // base - sizeof (Rgba), // xStride - 0, // yStride - 1, // xSampling - 1)); // ySampling - } - - if (_writeC) - { - fb.insert ("RY", - Slice (HALF, // type - (char *) &_tmpBuf[-_xMin].r, // base - sizeof (Rgba) * 2, // xStride - 0, // yStride - 2, // xSampling - 2)); // ySampling - - fb.insert ("BY", - Slice (HALF, // type - (char *) &_tmpBuf[-_xMin].b, // base - sizeof (Rgba) * 2, // xStride - 0, // yStride - 2, // xSampling - 2)); // ySampling - } - - if (_writeA) - { - fb.insert ("A", - Slice (HALF, // type - (char *) &_tmpBuf[-_xMin].a, // base - sizeof (Rgba), // xStride - 0, // yStride - 1, // xSampling - 1)); // ySampling - } - - _outputFile.setFrameBuffer (fb); + FrameBuffer fb; + + if (_writeY) + { + fb.insert ("Y", + Slice (HALF, // type + (char *) &_tmpBuf[-_xMin].g, // base + sizeof (Rgba), // xStride + 0, // yStride + 1, // xSampling + 1)); // ySampling + } + + if (_writeC) + { + fb.insert ("RY", + Slice (HALF, // type + (char *) &_tmpBuf[-_xMin].r, // base + sizeof (Rgba) * 2, // xStride + 0, // yStride + 2, // xSampling + 2)); // ySampling + + fb.insert ("BY", + Slice (HALF, // type + (char *) &_tmpBuf[-_xMin].b, // base + sizeof (Rgba) * 2, // xStride + 0, // yStride + 2, // xSampling + 2)); // ySampling + } + + if (_writeA) + { + fb.insert ("A", + Slice (HALF, // type + (char *) &_tmpBuf[-_xMin].a, // base + sizeof (Rgba), // xStride + 0, // yStride + 1, // xSampling + 1)); // ySampling + } + + _outputFile.setFrameBuffer (fb); } _fbBase = base; @@ -357,138 +358,138 @@ RgbaOutputFile::ToYca::writePixels (int numScanLines) { if (_fbBase == 0) { - THROW (Iex::ArgExc, "No frame buffer was specified as the " - "pixel data source for image file " - "\"" << _outputFile.fileName() << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "No frame buffer was specified as the " + "pixel data source for image file " + "\"" << _outputFile.fileName() << "\"."); } if (_writeY && !_writeC) { - // - // We are writing only luminance; filtering - // and subsampling are not necessary. - // - - for (int i = 0; i < numScanLines; ++i) - { - // - // Copy the next scan line from the caller's - // frame buffer into _tmpBuf. - // - - for (int j = 0; j < _width; ++j) - { - _tmpBuf[j] = _fbBase[_fbYStride * _currentScanLine + - _fbXStride * (j + _xMin)]; - } - - // - // Convert the scan line from RGB to luminance/chroma, - // and store the result in the output file. - // - - RGBAtoYCA (_yw, _width, _writeA, _tmpBuf, _tmpBuf); - _outputFile.writePixels (1); - - ++_linesConverted; - - if (_lineOrder == INCREASING_Y) - ++_currentScanLine; - else - --_currentScanLine; - } + // + // We are writing only luminance; filtering + // and subsampling are not necessary. + // + + for (int i = 0; i < numScanLines; ++i) + { + // + // Copy the next scan line from the caller's + // frame buffer into _tmpBuf. + // + + for (int j = 0; j < _width; ++j) + { + _tmpBuf[j] = _fbBase[_fbYStride * _currentScanLine + + _fbXStride * (j + _xMin)]; + } + + // + // Convert the scan line from RGB to luminance/chroma, + // and store the result in the output file. + // + + RGBAtoYCA (_yw, _width, _writeA, _tmpBuf, _tmpBuf); + _outputFile.writePixels (1); + + ++_linesConverted; + + if (_lineOrder == INCREASING_Y) + ++_currentScanLine; + else + --_currentScanLine; + } } else { - // - // We are writing chroma; the pixels must be filtered and subsampled. - // - - for (int i = 0; i < numScanLines; ++i) - { - // - // Copy the next scan line from the caller's - // frame buffer into _tmpBuf. - // - - for (int j = 0; j < _width; ++j) - { - _tmpBuf[j + N2] = _fbBase[_fbYStride * _currentScanLine + - _fbXStride * (j + _xMin)]; - } - - // - // Convert the scan line from RGB to luminance/chroma. - // - - RGBAtoYCA (_yw, _width, _writeA, _tmpBuf + N2, _tmpBuf + N2); - - // - // Append N2 copies of the first and last pixel to the - // beginning and end of the scan line. - // - - padTmpBuf (); - - // - // Filter and subsample the scan line's chroma channels - // horizontally; store the result in _buf. - // - - rotateBuffers(); - decimateChromaHoriz (_width, _tmpBuf, _buf[N - 1]); - - // - // If this is the first scan line in the image, - // store N2 more copies of the scan line in _buf. - // - - if (_linesConverted == 0) - { - for (int j = 0; j < N2; ++j) - duplicateLastBuffer(); - } - - ++_linesConverted; - - // - // If we have have converted at least N2 scan lines from - // RGBA to luminance/chroma, then we can start to filter - // and subsample vertically, and store pixels in the - // output file. - // - - if (_linesConverted > N2) - decimateChromaVertAndWriteScanLine(); - - // - // If we have already converted the last scan line in - // the image to luminance/chroma, filter, subsample and - // store the remaining scan lines in _buf. - // - - if (_linesConverted >= _height) - { - for (int j = 0; j < N2 - _height; ++j) - duplicateLastBuffer(); - - duplicateSecondToLastBuffer(); - ++_linesConverted; - decimateChromaVertAndWriteScanLine(); - - for (int j = 1; j < min (_height, N2); ++j) - { - duplicateLastBuffer(); - ++_linesConverted; - decimateChromaVertAndWriteScanLine(); - } - } - - if (_lineOrder == INCREASING_Y) - ++_currentScanLine; - else - --_currentScanLine; - } + // + // We are writing chroma; the pixels must be filtered and subsampled. + // + + for (int i = 0; i < numScanLines; ++i) + { + // + // Copy the next scan line from the caller's + // frame buffer into _tmpBuf. + // + + for (int j = 0; j < _width; ++j) + { + _tmpBuf[j + N2] = _fbBase[_fbYStride * _currentScanLine + + _fbXStride * (j + _xMin)]; + } + + // + // Convert the scan line from RGB to luminance/chroma. + // + + RGBAtoYCA (_yw, _width, _writeA, _tmpBuf + N2, _tmpBuf + N2); + + // + // Append N2 copies of the first and last pixel to the + // beginning and end of the scan line. + // + + padTmpBuf (); + + // + // Filter and subsample the scan line's chroma channels + // horizontally; store the result in _buf. + // + + rotateBuffers(); + decimateChromaHoriz (_width, _tmpBuf, _buf[N - 1]); + + // + // If this is the first scan line in the image, + // store N2 more copies of the scan line in _buf. + // + + if (_linesConverted == 0) + { + for (int j = 0; j < N2; ++j) + duplicateLastBuffer(); + } + + ++_linesConverted; + + // + // If we have have converted at least N2 scan lines from + // RGBA to luminance/chroma, then we can start to filter + // and subsample vertically, and store pixels in the + // output file. + // + + if (_linesConverted > N2) + decimateChromaVertAndWriteScanLine(); + + // + // If we have already converted the last scan line in + // the image to luminance/chroma, filter, subsample and + // store the remaining scan lines in _buf. + // + + if (_linesConverted >= _height) + { + for (int j = 0; j < N2 - _height; ++j) + duplicateLastBuffer(); + + duplicateSecondToLastBuffer(); + ++_linesConverted; + decimateChromaVertAndWriteScanLine(); + + for (int j = 1; j < min (_height, N2); ++j) + { + duplicateLastBuffer(); + ++_linesConverted; + decimateChromaVertAndWriteScanLine(); + } + } + + if (_lineOrder == INCREASING_Y) + ++_currentScanLine; + else + --_currentScanLine; + } } } @@ -505,8 +506,8 @@ RgbaOutputFile::ToYca::padTmpBuf () { for (int i = 0; i < N2; ++i) { - _tmpBuf[i] = _tmpBuf[N2]; - _tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2]; + _tmpBuf[i] = _tmpBuf[N2]; + _tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2]; } } @@ -517,7 +518,7 @@ RgbaOutputFile::ToYca::rotateBuffers () Rgba *tmp = _buf[0]; for (int i = 0; i < N - 1; ++i) - _buf[i] = _buf[i + 1]; + _buf[i] = _buf[i + 1]; _buf[N - 1] = tmp; } @@ -543,20 +544,20 @@ void RgbaOutputFile::ToYca::decimateChromaVertAndWriteScanLine () { if (_linesConverted & 1) - memcpy (_tmpBuf, _buf[N2], _width * sizeof (Rgba)); + memcpy (_tmpBuf, _buf[N2], _width * sizeof (Rgba)); else - decimateChromaVert (_width, _buf, _tmpBuf); + decimateChromaVert (_width, _buf, _tmpBuf); if (_writeY && _writeC) - roundYCA (_width, _roundY, _roundC, _tmpBuf, _tmpBuf); + roundYCA (_width, _roundY, _roundC, _tmpBuf, _tmpBuf); _outputFile.writePixels (1); } RgbaOutputFile::RgbaOutputFile (const char name[], - const Header &header, - RgbaChannels rgbaChannels, + const Header &header, + RgbaChannels rgbaChannels, int numThreads): _outputFile (0), _toYca (0) @@ -566,13 +567,13 @@ RgbaOutputFile::RgbaOutputFile (const char name[], _outputFile = new OutputFile (name, hd, numThreads); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _toYca = new ToYca (*_outputFile, rgbaChannels); + _toYca = new ToYca (*_outputFile, rgbaChannels); } -RgbaOutputFile::RgbaOutputFile (OStream &os, - const Header &header, - RgbaChannels rgbaChannels, +RgbaOutputFile::RgbaOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + RgbaChannels rgbaChannels, int numThreads): _outputFile (0), _toYca (0) @@ -582,65 +583,65 @@ RgbaOutputFile::RgbaOutputFile (OStream &os, _outputFile = new OutputFile (os, hd, numThreads); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _toYca = new ToYca (*_outputFile, rgbaChannels); + _toYca = new ToYca (*_outputFile, rgbaChannels); } RgbaOutputFile::RgbaOutputFile (const char name[], - const Imath::Box2i &displayWindow, - const Imath::Box2i &dataWindow, - RgbaChannels rgbaChannels, - float pixelAspectRatio, - const Imath::V2f screenWindowCenter, - float screenWindowWidth, - LineOrder lineOrder, - Compression compression, + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow, + RgbaChannels rgbaChannels, + float pixelAspectRatio, + const IMATH_NAMESPACE::V2f screenWindowCenter, + float screenWindowWidth, + LineOrder lineOrder, + Compression compression, int numThreads): _outputFile (0), _toYca (0) { Header hd (displayWindow, - dataWindow.isEmpty()? displayWindow: dataWindow, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + dataWindow.isEmpty()? displayWindow: dataWindow, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); insertChannels (hd, rgbaChannels); _outputFile = new OutputFile (name, hd, numThreads); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _toYca = new ToYca (*_outputFile, rgbaChannels); + _toYca = new ToYca (*_outputFile, rgbaChannels); } RgbaOutputFile::RgbaOutputFile (const char name[], - int width, - int height, - RgbaChannels rgbaChannels, - float pixelAspectRatio, - const Imath::V2f screenWindowCenter, - float screenWindowWidth, - LineOrder lineOrder, - Compression compression, + int width, + int height, + RgbaChannels rgbaChannels, + float pixelAspectRatio, + const IMATH_NAMESPACE::V2f screenWindowCenter, + float screenWindowWidth, + LineOrder lineOrder, + Compression compression, int numThreads): _outputFile (0), _toYca (0) { Header hd (width, - height, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + height, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); insertChannels (hd, rgbaChannels); _outputFile = new OutputFile (name, hd, numThreads); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _toYca = new ToYca (*_outputFile, rgbaChannels); + _toYca = new ToYca (*_outputFile, rgbaChannels); } @@ -653,57 +654,57 @@ RgbaOutputFile::~RgbaOutputFile () void RgbaOutputFile::setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride) + size_t xStride, + size_t yStride) { if (_toYca) { - Lock lock (*_toYca); - _toYca->setFrameBuffer (base, xStride, yStride); + Lock lock (*_toYca); + _toYca->setFrameBuffer (base, xStride, yStride); } else { - size_t xs = xStride * sizeof (Rgba); - size_t ys = yStride * sizeof (Rgba); + size_t xs = xStride * sizeof (Rgba); + size_t ys = yStride * sizeof (Rgba); - FrameBuffer fb; + FrameBuffer fb; - fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys)); - fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys)); - fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys)); - fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys)); + fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys)); + fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys)); + fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys)); + fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys)); - _outputFile->setFrameBuffer (fb); + _outputFile->setFrameBuffer (fb); } } -void +void RgbaOutputFile::writePixels (int numScanLines) { if (_toYca) { - Lock lock (*_toYca); - _toYca->writePixels (numScanLines); + Lock lock (*_toYca); + _toYca->writePixels (numScanLines); } else { - _outputFile->writePixels (numScanLines); + _outputFile->writePixels (numScanLines); } } -int +int RgbaOutputFile::currentScanLine () const { if (_toYca) { - Lock lock (*_toYca); - return _toYca->currentScanLine(); + Lock lock (*_toYca); + return _toYca->currentScanLine(); } else { - return _outputFile->currentScanLine(); + return _outputFile->currentScanLine(); } } @@ -722,35 +723,35 @@ RgbaOutputFile::frameBuffer () const } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & RgbaOutputFile::displayWindow () const { return _outputFile->header().displayWindow(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & RgbaOutputFile::dataWindow () const { return _outputFile->header().dataWindow(); } -float +float RgbaOutputFile::pixelAspectRatio () const { return _outputFile->header().pixelAspectRatio(); } -const Imath::V2f +const IMATH_NAMESPACE::V2f RgbaOutputFile::screenWindowCenter () const { return _outputFile->header().screenWindowCenter(); } -float +float RgbaOutputFile::screenWindowWidth () const { return _outputFile->header().screenWindowWidth(); @@ -778,25 +779,25 @@ RgbaOutputFile::channels () const } -void +void RgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[]) { _outputFile->updatePreviewImage (newPixels); } -void +void RgbaOutputFile::setYCRounding (unsigned int roundY, unsigned int roundC) { if (_toYca) { - Lock lock (*_toYca); - _toYca->setYCRounding (roundY, roundC); + Lock lock (*_toYca); + _toYca->setYCRounding (roundY, roundC); } } -void +void RgbaOutputFile::breakScanLine (int y, int offset, int length, char c) { _outputFile->breakScanLine (y, offset, length, c); @@ -811,9 +812,9 @@ class RgbaInputFile::FromYca: public Mutex ~FromYca (); void setFrameBuffer (Rgba *base, - size_t xStride, - size_t yStride, - const string &channelNamePrefix); + size_t xStride, + size_t yStride, + const string &channelNamePrefix); void readPixels (int scanLine1, int scanLine2); @@ -846,7 +847,7 @@ class RgbaInputFile::FromYca: public Mutex RgbaInputFile::FromYca::FromYca (InputFile &inputFile, - RgbaChannels rgbaChannels) + RgbaChannels rgbaChannels) : _inputFile (inputFile) { @@ -868,10 +869,10 @@ RgbaInputFile::FromYca::FromYca (InputFile &inputFile, _bufBase = new Rgba[(_width + pad) * (N + 2 + 3)]; for (int i = 0; i < N + 2; ++i) - _buf1[i] = _bufBase + (i * (_width + pad)); - + _buf1[i] = _bufBase + (i * (_width + pad)); + for (int i = 0; i < 3; ++i) - _buf2[i] = _bufBase + ((i + N + 2) * (_width + pad)); + _buf2[i] = _bufBase + ((i + N + 2) * (_width + pad)); _tmpBuf = new Rgba[_width + N - 1]; @@ -890,54 +891,54 @@ RgbaInputFile::FromYca::~FromYca () void RgbaInputFile::FromYca::setFrameBuffer (Rgba *base, - size_t xStride, - size_t yStride, - const string &channelNamePrefix) + size_t xStride, + size_t yStride, + const string &channelNamePrefix) { if (_fbBase == 0) { - FrameBuffer fb; - - fb.insert (channelNamePrefix + "Y", - Slice (HALF, // type - (char *) &_tmpBuf[N2 - _xMin].g, // base - sizeof (Rgba), // xStride - 0, // yStride - 1, // xSampling - 1, // ySampling - 0.5)); // fillValue - - if (_readC) - { - fb.insert (channelNamePrefix + "RY", - Slice (HALF, // type - (char *) &_tmpBuf[N2 - _xMin].r, // base - sizeof (Rgba) * 2, // xStride - 0, // yStride - 2, // xSampling - 2, // ySampling - 0.0)); // fillValue - - fb.insert (channelNamePrefix + "BY", - Slice (HALF, // type - (char *) &_tmpBuf[N2 - _xMin].b, // base - sizeof (Rgba) * 2, // xStride - 0, // yStride - 2, // xSampling - 2, // ySampling - 0.0)); // fillValue - } - - fb.insert (channelNamePrefix + "A", - Slice (HALF, // type - (char *) &_tmpBuf[N2 - _xMin].a, // base - sizeof (Rgba), // xStride - 0, // yStride - 1, // xSampling - 1, // ySampling - 1.0)); // fillValue - - _inputFile.setFrameBuffer (fb); + FrameBuffer fb; + + fb.insert (channelNamePrefix + "Y", + Slice (HALF, // type + (char *) &_tmpBuf[N2 - _xMin].g, // base + sizeof (Rgba), // xStride + 0, // yStride + 1, // xSampling + 1, // ySampling + 0.5)); // fillValue + + if (_readC) + { + fb.insert (channelNamePrefix + "RY", + Slice (HALF, // type + (char *) &_tmpBuf[N2 - _xMin].r, // base + sizeof (Rgba) * 2, // xStride + 0, // yStride + 2, // xSampling + 2, // ySampling + 0.0)); // fillValue + + fb.insert (channelNamePrefix + "BY", + Slice (HALF, // type + (char *) &_tmpBuf[N2 - _xMin].b, // base + sizeof (Rgba) * 2, // xStride + 0, // yStride + 2, // xSampling + 2, // ySampling + 0.0)); // fillValue + } + + fb.insert (channelNamePrefix + "A", + Slice (HALF, // type + (char *) &_tmpBuf[N2 - _xMin].a, // base + sizeof (Rgba), // xStride + 0, // yStride + 1, // xSampling + 1, // ySampling + 1.0)); // fillValue + + _inputFile.setFrameBuffer (fb); } _fbBase = base; @@ -946,7 +947,7 @@ RgbaInputFile::FromYca::setFrameBuffer (Rgba *base, } -void +void RgbaInputFile::FromYca::readPixels (int scanLine1, int scanLine2) { int minY = min (scanLine1, scanLine2); @@ -954,25 +955,25 @@ RgbaInputFile::FromYca::readPixels (int scanLine1, int scanLine2) if (_lineOrder == INCREASING_Y) { - for (int y = minY; y <= maxY; ++y) - readPixels (y); + for (int y = minY; y <= maxY; ++y) + readPixels (y); } else { - for (int y = maxY; y >= minY; --y) - readPixels (y); + for (int y = maxY; y >= minY; --y) + readPixels (y); } } -void +void RgbaInputFile::FromYca::readPixels (int scanLine) { if (_fbBase == 0) { - THROW (Iex::ArgExc, "No frame buffer was specified as the " - "pixel data destination for image file " - "\"" << _inputFile.fileName() << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "No frame buffer was specified as the " + "pixel data destination for image file " + "\"" << _inputFile.fileName() << "\"."); } // @@ -1007,70 +1008,70 @@ RgbaInputFile::FromYca::readPixels (int scanLine) int dy = scanLine - _currentScanLine; if (abs (dy) < N + 2) - rotateBuf1 (dy); + rotateBuf1 (dy); if (abs (dy) < 3) - rotateBuf2 (dy); + rotateBuf2 (dy); if (dy < 0) { - { - int n = min (-dy, N + 2); - int yMin = scanLine - N2 - 1; - - for (int i = n - 1; i >= 0; --i) - readYCAScanLine (yMin + i, _buf1[i]); - } - - { - int n = min (-dy, 3); - - for (int i = 0; i < n; ++i) - { - if ((scanLine + i) & 1) - { - YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]); - } - else - { - reconstructChromaVert (_width, _buf1 + i, _buf2[i]); - YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]); - } - } - } + { + int n = min (-dy, N + 2); + int yMin = scanLine - N2 - 1; + + for (int i = n - 1; i >= 0; --i) + readYCAScanLine (yMin + i, _buf1[i]); + } + + { + int n = min (-dy, 3); + + for (int i = 0; i < n; ++i) + { + if ((scanLine + i) & 1) + { + YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]); + } + else + { + reconstructChromaVert (_width, _buf1 + i, _buf2[i]); + YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]); + } + } + } } else { - { - int n = min (dy, N + 2); - int yMax = scanLine + N2 + 1; - - for (int i = n - 1; i >= 0; --i) - readYCAScanLine (yMax - i, _buf1[N + 1 - i]); - } - - { - int n = min (dy, 3); - - for (int i = 2; i > 2 - n; --i) - { - if ((scanLine + i) & 1) - { - YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]); - } - else - { - reconstructChromaVert (_width, _buf1 + i, _buf2[i]); - YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]); - } - } - } + { + int n = min (dy, N + 2); + int yMax = scanLine + N2 + 1; + + for (int i = n - 1; i >= 0; --i) + readYCAScanLine (yMax - i, _buf1[N + 1 - i]); + } + + { + int n = min (dy, 3); + + for (int i = 2; i > 2 - n; --i) + { + if ((scanLine + i) & 1) + { + YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]); + } + else + { + reconstructChromaVert (_width, _buf1 + i, _buf2[i]); + YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]); + } + } + } } fixSaturation (_yw, _width, _buf2, _tmpBuf); for (int i = 0; i < _width; ++i) - _fbBase[_fbYStride * scanLine + _fbXStride * (i + _xMin)] = _tmpBuf[i]; + _fbBase[_fbYStride * scanLine + _fbXStride * (i + _xMin)] = _tmpBuf[i]; _currentScanLine = scanLine; } @@ -1084,10 +1085,10 @@ RgbaInputFile::FromYca::rotateBuf1 (int d) Rgba *tmp[N + 2]; for (int i = 0; i < N + 2; ++i) - tmp[i] = _buf1[i]; + tmp[i] = _buf1[i]; for (int i = 0; i < N + 2; ++i) - _buf1[i] = tmp[(i + d) % (N + 2)]; + _buf1[i] = tmp[(i + d) % (N + 2)]; } @@ -1099,10 +1100,10 @@ RgbaInputFile::FromYca::rotateBuf2 (int d) Rgba *tmp[3]; for (int i = 0; i < 3; ++i) - tmp[i] = _buf2[i]; + tmp[i] = _buf2[i]; for (int i = 0; i < 3; ++i) - _buf2[i] = tmp[(i + d) % 3]; + _buf2[i] = tmp[(i + d) % 3]; } @@ -1114,9 +1115,9 @@ RgbaInputFile::FromYca::readYCAScanLine (int y, Rgba *buf) // if (y < _yMin) - y = _yMin; + y = _yMin; else if (y > _yMax) - y = _yMax - 1; + y = _yMax - 1; // // Read scan line y into _tmpBuf. @@ -1131,21 +1132,21 @@ RgbaInputFile::FromYca::readYCAScanLine (int y, Rgba *buf) if (!_readC) { - for (int i = 0; i < _width; ++i) - { - _tmpBuf[i + N2].r = 0; - _tmpBuf[i + N2].b = 0; - } + for (int i = 0; i < _width; ++i) + { + _tmpBuf[i + N2].r = 0; + _tmpBuf[i + N2].b = 0; + } } if (y & 1) { - memcpy (buf, _tmpBuf + N2, _width * sizeof (Rgba)); + memcpy (buf, _tmpBuf + N2, _width * sizeof (Rgba)); } else { - padTmpBuf(); - reconstructChromaHoriz (_width, _tmpBuf, buf); + padTmpBuf(); + reconstructChromaHoriz (_width, _tmpBuf, buf); } } @@ -1155,8 +1156,8 @@ RgbaInputFile::FromYca::padTmpBuf () { for (int i = 0; i < N2; ++i) { - _tmpBuf[i] = _tmpBuf[N2]; - _tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2]; + _tmpBuf[i] = _tmpBuf[N2]; + _tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2]; } } @@ -1169,11 +1170,11 @@ RgbaInputFile::RgbaInputFile (const char name[], int numThreads): RgbaChannels rgbaChannels = channels(); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _fromYca = new FromYca (*_inputFile, rgbaChannels); + _fromYca = new FromYca (*_inputFile, rgbaChannels); } -RgbaInputFile::RgbaInputFile (IStream &is, int numThreads): +RgbaInputFile::RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads): _inputFile (new InputFile (is, numThreads)), _fromYca (0), _channelNamePrefix ("") @@ -1181,13 +1182,13 @@ RgbaInputFile::RgbaInputFile (IStream &is, int numThreads): RgbaChannels rgbaChannels = channels(); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _fromYca = new FromYca (*_inputFile, rgbaChannels); + _fromYca = new FromYca (*_inputFile, rgbaChannels); } RgbaInputFile::RgbaInputFile (const char name[], - const string &layerName, - int numThreads) + const string &layerName, + int numThreads) : _inputFile (new InputFile (name, numThreads)), _fromYca (0), @@ -1196,13 +1197,13 @@ RgbaInputFile::RgbaInputFile (const char name[], RgbaChannels rgbaChannels = channels(); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _fromYca = new FromYca (*_inputFile, rgbaChannels); + _fromYca = new FromYca (*_inputFile, rgbaChannels); } -RgbaInputFile::RgbaInputFile (IStream &is, - const string &layerName, - int numThreads) +RgbaInputFile::RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + const string &layerName, + int numThreads) : _inputFile (new InputFile (is, numThreads)), _fromYca (0), @@ -1211,7 +1212,7 @@ RgbaInputFile::RgbaInputFile (IStream &is, RgbaChannels rgbaChannels = channels(); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _fromYca = new FromYca (*_inputFile, rgbaChannels); + _fromYca = new FromYca (*_inputFile, rgbaChannels); } @@ -1222,50 +1223,50 @@ RgbaInputFile::~RgbaInputFile () } -void +void RgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride) { if (_fromYca) { - Lock lock (*_fromYca); - _fromYca->setFrameBuffer (base, xStride, yStride, _channelNamePrefix); + Lock lock (*_fromYca); + _fromYca->setFrameBuffer (base, xStride, yStride, _channelNamePrefix); } else { - size_t xs = xStride * sizeof (Rgba); - size_t ys = yStride * sizeof (Rgba); - - FrameBuffer fb; - - fb.insert (_channelNamePrefix + "R", - Slice (HALF, - (char *) &base[0].r, - xs, ys, - 1, 1, // xSampling, ySampling - 0.0)); // fillValue - - fb.insert (_channelNamePrefix + "G", - Slice (HALF, - (char *) &base[0].g, - xs, ys, - 1, 1, // xSampling, ySampling - 0.0)); // fillValue - - fb.insert (_channelNamePrefix + "B", - Slice (HALF, - (char *) &base[0].b, - xs, ys, - 1, 1, // xSampling, ySampling - 0.0)); // fillValue - - fb.insert (_channelNamePrefix + "A", - Slice (HALF, - (char *) &base[0].a, - xs, ys, - 1, 1, // xSampling, ySampling - 1.0)); // fillValue - - _inputFile->setFrameBuffer (fb); + size_t xs = xStride * sizeof (Rgba); + size_t ys = yStride * sizeof (Rgba); + + FrameBuffer fb; + + fb.insert (_channelNamePrefix + "R", + Slice (HALF, + (char *) &base[0].r, + xs, ys, + 1, 1, // xSampling, ySampling + 0.0)); // fillValue + + fb.insert (_channelNamePrefix + "G", + Slice (HALF, + (char *) &base[0].g, + xs, ys, + 1, 1, // xSampling, ySampling + 0.0)); // fillValue + + fb.insert (_channelNamePrefix + "B", + Slice (HALF, + (char *) &base[0].b, + xs, ys, + 1, 1, // xSampling, ySampling + 0.0)); // fillValue + + fb.insert (_channelNamePrefix + "A", + Slice (HALF, + (char *) &base[0].a, + xs, ys, + 1, 1, // xSampling, ySampling + 1.0)); // fillValue + + _inputFile->setFrameBuffer (fb); } } @@ -1281,29 +1282,29 @@ RgbaInputFile::setLayerName (const string &layerName) RgbaChannels rgbaChannels = channels(); if (rgbaChannels & (WRITE_Y | WRITE_C)) - _fromYca = new FromYca (*_inputFile, rgbaChannels); + _fromYca = new FromYca (*_inputFile, rgbaChannels); FrameBuffer fb; _inputFile->setFrameBuffer (fb); } -void +void RgbaInputFile::readPixels (int scanLine1, int scanLine2) { if (_fromYca) { - Lock lock (*_fromYca); - _fromYca->readPixels (scanLine1, scanLine2); + Lock lock (*_fromYca); + _fromYca->readPixels (scanLine1, scanLine2); } else { - _inputFile->readPixels (scanLine1, scanLine2); + _inputFile->readPixels (scanLine1, scanLine2); } } -void +void RgbaInputFile::readPixels (int scanLine) { readPixels (scanLine, scanLine); @@ -1331,42 +1332,42 @@ RgbaInputFile::fileName () const } -const FrameBuffer & +const FrameBuffer & RgbaInputFile::frameBuffer () const { return _inputFile->frameBuffer(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & RgbaInputFile::displayWindow () const { return _inputFile->header().displayWindow(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & RgbaInputFile::dataWindow () const { return _inputFile->header().dataWindow(); } -float +float RgbaInputFile::pixelAspectRatio () const { return _inputFile->header().pixelAspectRatio(); } -const Imath::V2f +const IMATH_NAMESPACE::V2f RgbaInputFile::screenWindowCenter () const { return _inputFile->header().screenWindowCenter(); } -float +float RgbaInputFile::screenWindowWidth () const { return _inputFile->header().screenWindowWidth(); @@ -1387,7 +1388,7 @@ RgbaInputFile::compression () const } -RgbaChannels +RgbaChannels RgbaInputFile::channels () const { return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix); @@ -1401,4 +1402,4 @@ RgbaInputFile::version () const } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfRgbaFile.h b/3rdparty/openexr/IlmImf/ImfRgbaFile.h index 95e79d31f7..ace1859899 100644 --- a/3rdparty/openexr/IlmImf/ImfRgbaFile.h +++ b/3rdparty/openexr/IlmImf/ImfRgbaFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -47,21 +47,19 @@ // //----------------------------------------------------------------------------- -#include -#include -#include +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfRgba.h" #include "ImathVec.h" #include "ImathBox.h" #include "half.h" -#include +#include "ImfThreading.h" #include +#include "ImfNamespace.h" +#include "ImfForward.h" -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -class OutputFile; -class InputFile; -struct PreviewRgba; // // RGBA output file. @@ -75,9 +73,10 @@ class RgbaOutputFile // Constructor -- header is constructed by the caller //--------------------------------------------------- + IMF_EXPORT RgbaOutputFile (const char name[], - const Header &header, - RgbaChannels rgbaChannels = WRITE_RGBA, + const Header &header, + RgbaChannels rgbaChannels = WRITE_RGBA, int numThreads = globalThreadCount()); @@ -87,9 +86,10 @@ class RgbaOutputFile // automatically close the file. //---------------------------------------------------- - RgbaOutputFile (OStream &os, - const Header &header, - RgbaChannels rgbaChannels = WRITE_RGBA, + IMF_EXPORT + RgbaOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + RgbaChannels rgbaChannels = WRITE_RGBA, int numThreads = globalThreadCount()); @@ -98,15 +98,16 @@ class RgbaOutputFile // call arguments (empty dataWindow means "same as displayWindow") //---------------------------------------------------------------- + IMF_EXPORT RgbaOutputFile (const char name[], - const Imath::Box2i &displayWindow, - const Imath::Box2i &dataWindow = Imath::Box2i(), - RgbaChannels rgbaChannels = WRITE_RGBA, - float pixelAspectRatio = 1, - const Imath::V2f screenWindowCenter = Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression compression = PIZ_COMPRESSION, + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow = IMATH_NAMESPACE::Box2i(), + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = PIZ_COMPRESSION, int numThreads = globalThreadCount()); @@ -116,15 +117,16 @@ class RgbaOutputFile // Box2i (V2i (0, 0), V2i (width - 1, height -1)) //----------------------------------------------- + IMF_EXPORT RgbaOutputFile (const char name[], - int width, - int height, - RgbaChannels rgbaChannels = WRITE_RGBA, - float pixelAspectRatio = 1, - const Imath::V2f screenWindowCenter = Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression compression = PIZ_COMPRESSION, + int width, + int height, + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = PIZ_COMPRESSION, int numThreads = globalThreadCount()); @@ -132,6 +134,7 @@ class RgbaOutputFile // Destructor //----------- + IMF_EXPORT virtual ~RgbaOutputFile (); @@ -143,16 +146,19 @@ class RgbaOutputFile // //------------------------------------------------ + IMF_EXPORT void setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride); + size_t xStride, + size_t yStride); //--------------------------------------------- // Write pixel data (see class Imf::OutputFile) //--------------------------------------------- + IMF_EXPORT void writePixels (int numScanLines = 1); + IMF_EXPORT int currentScanLine () const; @@ -160,15 +166,25 @@ class RgbaOutputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; + IMF_EXPORT const FrameBuffer & frameBuffer () const; - const Imath::Box2i & displayWindow () const; - const Imath::Box2i & dataWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & displayWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & dataWindow () const; + IMF_EXPORT float pixelAspectRatio () const; - const Imath::V2f screenWindowCenter () const; + IMF_EXPORT + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + IMF_EXPORT float screenWindowWidth () const; + IMF_EXPORT LineOrder lineOrder () const; + IMF_EXPORT Compression compression () const; + IMF_EXPORT RgbaChannels channels () const; @@ -176,6 +192,7 @@ class RgbaOutputFile // Update the preview image (see Imf::OutputFile::updatePreviewImage()) // -------------------------------------------------------------------- + IMF_EXPORT void updatePreviewImage (const PreviewRgba[]); @@ -193,8 +210,9 @@ class RgbaOutputFile // without chroma, then no rounding is performed. //----------------------------------------------------------------------- + IMF_EXPORT void setYCRounding (unsigned int roundY, - unsigned int roundC); + unsigned int roundC); //---------------------------------------------------- @@ -207,10 +225,11 @@ class RgbaOutputFile // //---------------------------------------------------- + IMF_EXPORT void breakScanLine (int y, - int offset, - int length, - char c); + int offset, + int length, + char c); private: RgbaOutputFile (const RgbaOutputFile &); // not implemented @@ -236,6 +255,7 @@ class RgbaInputFile // destructor will automatically close the file. //------------------------------------------------------- + IMF_EXPORT RgbaInputFile (const char name[], int numThreads = globalThreadCount()); @@ -246,7 +266,8 @@ class RgbaInputFile // close the file. //----------------------------------------------------------- - RgbaInputFile (IStream &is, int numThreads = globalThreadCount()); + IMF_EXPORT + RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount()); //-------------------------------------------------------------- @@ -255,19 +276,22 @@ class RgbaInputFile // are expected to be layerName.R, layerName.G, etc. //-------------------------------------------------------------- + IMF_EXPORT RgbaInputFile (const char name[], - const std::string &layerName, - int numThreads = globalThreadCount()); + const std::string &layerName, + int numThreads = globalThreadCount()); - RgbaInputFile (IStream &is, - const std::string &layerName, - int numThreads = globalThreadCount()); + IMF_EXPORT + RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + const std::string &layerName, + int numThreads = globalThreadCount()); //----------- // Destructor //----------- + IMF_EXPORT virtual ~RgbaInputFile (); @@ -279,9 +303,10 @@ class RgbaInputFile // //----------------------------------------------------- + IMF_EXPORT void setFrameBuffer (Rgba *base, - size_t xStride, - size_t yStride); + size_t xStride, + size_t yStride); //---------------------------------------------------------------- @@ -291,6 +316,7 @@ class RgbaInputFile // called at least once before the next call to readPixels(). //---------------------------------------------------------------- + IMF_EXPORT void setLayerName (const std::string &layerName); @@ -298,7 +324,9 @@ class RgbaInputFile // Read pixel data (see class Imf::InputFile) //------------------------------------------- + IMF_EXPORT void readPixels (int scanLine1, int scanLine2); + IMF_EXPORT void readPixels (int scanLine); @@ -306,17 +334,29 @@ class RgbaInputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; + IMF_EXPORT const FrameBuffer & frameBuffer () const; - const Imath::Box2i & displayWindow () const; - const Imath::Box2i & dataWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & displayWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & dataWindow () const; + IMF_EXPORT float pixelAspectRatio () const; - const Imath::V2f screenWindowCenter () const; + IMF_EXPORT + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + IMF_EXPORT float screenWindowWidth () const; + IMF_EXPORT LineOrder lineOrder () const; + IMF_EXPORT Compression compression () const; + IMF_EXPORT RgbaChannels channels () const; + IMF_EXPORT const char * fileName () const; + IMF_EXPORT bool isComplete () const; @@ -324,6 +364,7 @@ class RgbaInputFile // Access to the file format version //---------------------------------- + IMF_EXPORT int version () const; private: @@ -339,6 +380,10 @@ class RgbaInputFile }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfRgbaYca.cpp b/3rdparty/openexr/IlmImf/ImfRgbaYca.cpp index e1f3340b2d..c6212f3ac4 100644 --- a/3rdparty/openexr/IlmImf/ImfRgbaYca.cpp +++ b/3rdparty/openexr/IlmImf/ImfRgbaYca.cpp @@ -46,10 +46,12 @@ #include #include -using namespace Imath; +using namespace IMATH_NAMESPACE; using namespace std; +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { namespace RgbaYca { @@ -63,78 +65,78 @@ computeYw (const Chromaticities &cr) void RGBAtoYCA (const V3f &yw, - int n, - bool aIsValid, - const Rgba rgbaIn[/*n*/], - Rgba ycaOut[/*n*/]) + int n, + bool aIsValid, + const Rgba rgbaIn[/*n*/], + Rgba ycaOut[/*n*/]) { for (int i = 0; i < n; ++i) { - Rgba in = rgbaIn[i]; - Rgba &out = ycaOut[i]; - - // - // Conversion to YCA and subsequent chroma subsampling - // work only if R, G and B are finite and non-negative. - // - - if (!in.r.isFinite() || in.r < 0) - in.r = 0; - - if (!in.g.isFinite() || in.g < 0) - in.g = 0; - - if (!in.b.isFinite() || in.b < 0) - in.b = 0; - - if (in.r == in.g && in.g == in.b) - { - // - // Special case -- R, G and B are equal. To avoid rounding - // errors, we explicitly set the output luminance channel - // to G, and the chroma channels to 0. - // - // The special cases here and in YCAtoRGBA() ensure that - // converting black-and white images from RGBA to YCA and - // back is lossless. - // - - out.r = 0; - out.g = in.g; - out.b = 0; - } - else - { - out.g = in.r * yw.x + in.g * yw.y + in.b * yw.z; - - float Y = out.g; - - if (abs (in.r - Y) < HALF_MAX * Y) - out.r = (in.r - Y) / Y; - else - out.r = 0; - - if (abs (in.b - Y) < HALF_MAX * Y) - out.b = (in.b - Y) / Y; - else - out.b = 0; - } - - if (aIsValid) - out.a = in.a; - else - out.a = 1; + Rgba in = rgbaIn[i]; + Rgba &out = ycaOut[i]; + + // + // Conversion to YCA and subsequent chroma subsampling + // work only if R, G and B are finite and non-negative. + // + + if (!in.r.isFinite() || in.r < 0) + in.r = 0; + + if (!in.g.isFinite() || in.g < 0) + in.g = 0; + + if (!in.b.isFinite() || in.b < 0) + in.b = 0; + + if (in.r == in.g && in.g == in.b) + { + // + // Special case -- R, G and B are equal. To avoid rounding + // errors, we explicitly set the output luminance channel + // to G, and the chroma channels to 0. + // + // The special cases here and in YCAtoRGBA() ensure that + // converting black-and white images from RGBA to YCA and + // back is lossless. + // + + out.r = 0; + out.g = in.g; + out.b = 0; + } + else + { + out.g = in.r * yw.x + in.g * yw.y + in.b * yw.z; + + float Y = out.g; + + if (abs (in.r - Y) < HALF_MAX * Y) + out.r = (in.r - Y) / Y; + else + out.r = 0; + + if (abs (in.b - Y) < HALF_MAX * Y) + out.b = (in.b - Y) / Y; + else + out.b = 0; + } + + if (aIsValid) + out.a = in.a; + else + out.a = 1; } } void decimateChromaHoriz (int n, - const Rgba ycaIn[/*n+N-1*/], - Rgba ycaOut[/*n*/]) + const Rgba ycaIn[/*n+N-1*/], + Rgba ycaOut[/*n*/]) { #ifdef DEBUG - assert (ycaIn != ycaOut); + assert (ycaIn != ycaOut); #endif int begin = N2; @@ -142,123 +144,123 @@ decimateChromaHoriz (int n, for (int i = begin, j = 0; i < end; ++i, ++j) { - if ((j & 1) == 0) - { - ycaOut[j].r = ycaIn[i - 13].r * 0.001064f + - ycaIn[i - 11].r * -0.003771f + - ycaIn[i - 9].r * 0.009801f + - ycaIn[i - 7].r * -0.021586f + - ycaIn[i - 5].r * 0.043978f + - ycaIn[i - 3].r * -0.093067f + - ycaIn[i - 1].r * 0.313659f + - ycaIn[i ].r * 0.499846f + - ycaIn[i + 1].r * 0.313659f + - ycaIn[i + 3].r * -0.093067f + - ycaIn[i + 5].r * 0.043978f + - ycaIn[i + 7].r * -0.021586f + - ycaIn[i + 9].r * 0.009801f + - ycaIn[i + 11].r * -0.003771f + - ycaIn[i + 13].r * 0.001064f; - - ycaOut[j].b = ycaIn[i - 13].b * 0.001064f + - ycaIn[i - 11].b * -0.003771f + - ycaIn[i - 9].b * 0.009801f + - ycaIn[i - 7].b * -0.021586f + - ycaIn[i - 5].b * 0.043978f + - ycaIn[i - 3].b * -0.093067f + - ycaIn[i - 1].b * 0.313659f + - ycaIn[i ].b * 0.499846f + - ycaIn[i + 1].b * 0.313659f + - ycaIn[i + 3].b * -0.093067f + - ycaIn[i + 5].b * 0.043978f + - ycaIn[i + 7].b * -0.021586f + - ycaIn[i + 9].b * 0.009801f + - ycaIn[i + 11].b * -0.003771f + - ycaIn[i + 13].b * 0.001064f; - } - - ycaOut[j].g = ycaIn[i].g; - ycaOut[j].a = ycaIn[i].a; + if ((j & 1) == 0) + { + ycaOut[j].r = ycaIn[i - 13].r * 0.001064f + + ycaIn[i - 11].r * -0.003771f + + ycaIn[i - 9].r * 0.009801f + + ycaIn[i - 7].r * -0.021586f + + ycaIn[i - 5].r * 0.043978f + + ycaIn[i - 3].r * -0.093067f + + ycaIn[i - 1].r * 0.313659f + + ycaIn[i ].r * 0.499846f + + ycaIn[i + 1].r * 0.313659f + + ycaIn[i + 3].r * -0.093067f + + ycaIn[i + 5].r * 0.043978f + + ycaIn[i + 7].r * -0.021586f + + ycaIn[i + 9].r * 0.009801f + + ycaIn[i + 11].r * -0.003771f + + ycaIn[i + 13].r * 0.001064f; + + ycaOut[j].b = ycaIn[i - 13].b * 0.001064f + + ycaIn[i - 11].b * -0.003771f + + ycaIn[i - 9].b * 0.009801f + + ycaIn[i - 7].b * -0.021586f + + ycaIn[i - 5].b * 0.043978f + + ycaIn[i - 3].b * -0.093067f + + ycaIn[i - 1].b * 0.313659f + + ycaIn[i ].b * 0.499846f + + ycaIn[i + 1].b * 0.313659f + + ycaIn[i + 3].b * -0.093067f + + ycaIn[i + 5].b * 0.043978f + + ycaIn[i + 7].b * -0.021586f + + ycaIn[i + 9].b * 0.009801f + + ycaIn[i + 11].b * -0.003771f + + ycaIn[i + 13].b * 0.001064f; + } + + ycaOut[j].g = ycaIn[i].g; + ycaOut[j].a = ycaIn[i].a; } } void decimateChromaVert (int n, - const Rgba * const ycaIn[N], - Rgba ycaOut[/*n*/]) + const Rgba * const ycaIn[N], + Rgba ycaOut[/*n*/]) { for (int i = 0; i < n; ++i) { - if ((i & 1) == 0) - { - ycaOut[i].r = ycaIn[ 0][i].r * 0.001064f + - ycaIn[ 2][i].r * -0.003771f + - ycaIn[ 4][i].r * 0.009801f + - ycaIn[ 6][i].r * -0.021586f + - ycaIn[ 8][i].r * 0.043978f + - ycaIn[10][i].r * -0.093067f + - ycaIn[12][i].r * 0.313659f + - ycaIn[13][i].r * 0.499846f + - ycaIn[14][i].r * 0.313659f + - ycaIn[16][i].r * -0.093067f + - ycaIn[18][i].r * 0.043978f + - ycaIn[20][i].r * -0.021586f + - ycaIn[22][i].r * 0.009801f + - ycaIn[24][i].r * -0.003771f + - ycaIn[26][i].r * 0.001064f; - - ycaOut[i].b = ycaIn[ 0][i].b * 0.001064f + - ycaIn[ 2][i].b * -0.003771f + - ycaIn[ 4][i].b * 0.009801f + - ycaIn[ 6][i].b * -0.021586f + - ycaIn[ 8][i].b * 0.043978f + - ycaIn[10][i].b * -0.093067f + - ycaIn[12][i].b * 0.313659f + - ycaIn[13][i].b * 0.499846f + - ycaIn[14][i].b * 0.313659f + - ycaIn[16][i].b * -0.093067f + - ycaIn[18][i].b * 0.043978f + - ycaIn[20][i].b * -0.021586f + - ycaIn[22][i].b * 0.009801f + - ycaIn[24][i].b * -0.003771f + - ycaIn[26][i].b * 0.001064f; - } - - ycaOut[i].g = ycaIn[13][i].g; - ycaOut[i].a = ycaIn[13][i].a; + if ((i & 1) == 0) + { + ycaOut[i].r = ycaIn[ 0][i].r * 0.001064f + + ycaIn[ 2][i].r * -0.003771f + + ycaIn[ 4][i].r * 0.009801f + + ycaIn[ 6][i].r * -0.021586f + + ycaIn[ 8][i].r * 0.043978f + + ycaIn[10][i].r * -0.093067f + + ycaIn[12][i].r * 0.313659f + + ycaIn[13][i].r * 0.499846f + + ycaIn[14][i].r * 0.313659f + + ycaIn[16][i].r * -0.093067f + + ycaIn[18][i].r * 0.043978f + + ycaIn[20][i].r * -0.021586f + + ycaIn[22][i].r * 0.009801f + + ycaIn[24][i].r * -0.003771f + + ycaIn[26][i].r * 0.001064f; + + ycaOut[i].b = ycaIn[ 0][i].b * 0.001064f + + ycaIn[ 2][i].b * -0.003771f + + ycaIn[ 4][i].b * 0.009801f + + ycaIn[ 6][i].b * -0.021586f + + ycaIn[ 8][i].b * 0.043978f + + ycaIn[10][i].b * -0.093067f + + ycaIn[12][i].b * 0.313659f + + ycaIn[13][i].b * 0.499846f + + ycaIn[14][i].b * 0.313659f + + ycaIn[16][i].b * -0.093067f + + ycaIn[18][i].b * 0.043978f + + ycaIn[20][i].b * -0.021586f + + ycaIn[22][i].b * 0.009801f + + ycaIn[24][i].b * -0.003771f + + ycaIn[26][i].b * 0.001064f; + } + + ycaOut[i].g = ycaIn[13][i].g; + ycaOut[i].a = ycaIn[13][i].a; } } void roundYCA (int n, - unsigned int roundY, - unsigned int roundC, - const Rgba ycaIn[/*n*/], - Rgba ycaOut[/*n*/]) + unsigned int roundY, + unsigned int roundC, + const Rgba ycaIn[/*n*/], + Rgba ycaOut[/*n*/]) { for (int i = 0; i < n; ++i) { - ycaOut[i].g = ycaIn[i].g.round (roundY); - ycaOut[i].a = ycaIn[i].a; - - if ((i & 1) == 0) - { - ycaOut[i].r = ycaIn[i].r.round (roundC); - ycaOut[i].b = ycaIn[i].b.round (roundC); - } + ycaOut[i].g = ycaIn[i].g.round (roundY); + ycaOut[i].a = ycaIn[i].a; + + if ((i & 1) == 0) + { + ycaOut[i].r = ycaIn[i].r.round (roundC); + ycaOut[i].b = ycaIn[i].b.round (roundC); + } } } void reconstructChromaHoriz (int n, - const Rgba ycaIn[/*n+N-1*/], - Rgba ycaOut[/*n*/]) + const Rgba ycaIn[/*n+N-1*/], + Rgba ycaOut[/*n*/]) { #ifdef DEBUG - assert (ycaIn != ycaOut); + assert (ycaIn != ycaOut); #endif int begin = N2; @@ -266,133 +268,133 @@ reconstructChromaHoriz (int n, for (int i = begin, j = 0; i < end; ++i, ++j) { - if (j & 1) - { - ycaOut[j].r = ycaIn[i - 13].r * 0.002128f + - ycaIn[i - 11].r * -0.007540f + - ycaIn[i - 9].r * 0.019597f + - ycaIn[i - 7].r * -0.043159f + - ycaIn[i - 5].r * 0.087929f + - ycaIn[i - 3].r * -0.186077f + - ycaIn[i - 1].r * 0.627123f + - ycaIn[i + 1].r * 0.627123f + - ycaIn[i + 3].r * -0.186077f + - ycaIn[i + 5].r * 0.087929f + - ycaIn[i + 7].r * -0.043159f + - ycaIn[i + 9].r * 0.019597f + - ycaIn[i + 11].r * -0.007540f + - ycaIn[i + 13].r * 0.002128f; - - ycaOut[j].b = ycaIn[i - 13].b * 0.002128f + - ycaIn[i - 11].b * -0.007540f + - ycaIn[i - 9].b * 0.019597f + - ycaIn[i - 7].b * -0.043159f + - ycaIn[i - 5].b * 0.087929f + - ycaIn[i - 3].b * -0.186077f + - ycaIn[i - 1].b * 0.627123f + - ycaIn[i + 1].b * 0.627123f + - ycaIn[i + 3].b * -0.186077f + - ycaIn[i + 5].b * 0.087929f + - ycaIn[i + 7].b * -0.043159f + - ycaIn[i + 9].b * 0.019597f + - ycaIn[i + 11].b * -0.007540f + - ycaIn[i + 13].b * 0.002128f; - } - else - { - ycaOut[j].r = ycaIn[i].r; - ycaOut[j].b = ycaIn[i].b; - } - - ycaOut[j].g = ycaIn[i].g; - ycaOut[j].a = ycaIn[i].a; + if (j & 1) + { + ycaOut[j].r = ycaIn[i - 13].r * 0.002128f + + ycaIn[i - 11].r * -0.007540f + + ycaIn[i - 9].r * 0.019597f + + ycaIn[i - 7].r * -0.043159f + + ycaIn[i - 5].r * 0.087929f + + ycaIn[i - 3].r * -0.186077f + + ycaIn[i - 1].r * 0.627123f + + ycaIn[i + 1].r * 0.627123f + + ycaIn[i + 3].r * -0.186077f + + ycaIn[i + 5].r * 0.087929f + + ycaIn[i + 7].r * -0.043159f + + ycaIn[i + 9].r * 0.019597f + + ycaIn[i + 11].r * -0.007540f + + ycaIn[i + 13].r * 0.002128f; + + ycaOut[j].b = ycaIn[i - 13].b * 0.002128f + + ycaIn[i - 11].b * -0.007540f + + ycaIn[i - 9].b * 0.019597f + + ycaIn[i - 7].b * -0.043159f + + ycaIn[i - 5].b * 0.087929f + + ycaIn[i - 3].b * -0.186077f + + ycaIn[i - 1].b * 0.627123f + + ycaIn[i + 1].b * 0.627123f + + ycaIn[i + 3].b * -0.186077f + + ycaIn[i + 5].b * 0.087929f + + ycaIn[i + 7].b * -0.043159f + + ycaIn[i + 9].b * 0.019597f + + ycaIn[i + 11].b * -0.007540f + + ycaIn[i + 13].b * 0.002128f; + } + else + { + ycaOut[j].r = ycaIn[i].r; + ycaOut[j].b = ycaIn[i].b; + } + + ycaOut[j].g = ycaIn[i].g; + ycaOut[j].a = ycaIn[i].a; } } void reconstructChromaVert (int n, - const Rgba * const ycaIn[N], - Rgba ycaOut[/*n*/]) + const Rgba * const ycaIn[N], + Rgba ycaOut[/*n*/]) { for (int i = 0; i < n; ++i) { - ycaOut[i].r = ycaIn[ 0][i].r * 0.002128f + - ycaIn[ 2][i].r * -0.007540f + - ycaIn[ 4][i].r * 0.019597f + - ycaIn[ 6][i].r * -0.043159f + - ycaIn[ 8][i].r * 0.087929f + - ycaIn[10][i].r * -0.186077f + - ycaIn[12][i].r * 0.627123f + - ycaIn[14][i].r * 0.627123f + - ycaIn[16][i].r * -0.186077f + - ycaIn[18][i].r * 0.087929f + - ycaIn[20][i].r * -0.043159f + - ycaIn[22][i].r * 0.019597f + - ycaIn[24][i].r * -0.007540f + - ycaIn[26][i].r * 0.002128f; - - ycaOut[i].b = ycaIn[ 0][i].b * 0.002128f + - ycaIn[ 2][i].b * -0.007540f + - ycaIn[ 4][i].b * 0.019597f + - ycaIn[ 6][i].b * -0.043159f + - ycaIn[ 8][i].b * 0.087929f + - ycaIn[10][i].b * -0.186077f + - ycaIn[12][i].b * 0.627123f + - ycaIn[14][i].b * 0.627123f + - ycaIn[16][i].b * -0.186077f + - ycaIn[18][i].b * 0.087929f + - ycaIn[20][i].b * -0.043159f + - ycaIn[22][i].b * 0.019597f + - ycaIn[24][i].b * -0.007540f + - ycaIn[26][i].b * 0.002128f; - - ycaOut[i].g = ycaIn[13][i].g; - ycaOut[i].a = ycaIn[13][i].a; + ycaOut[i].r = ycaIn[ 0][i].r * 0.002128f + + ycaIn[ 2][i].r * -0.007540f + + ycaIn[ 4][i].r * 0.019597f + + ycaIn[ 6][i].r * -0.043159f + + ycaIn[ 8][i].r * 0.087929f + + ycaIn[10][i].r * -0.186077f + + ycaIn[12][i].r * 0.627123f + + ycaIn[14][i].r * 0.627123f + + ycaIn[16][i].r * -0.186077f + + ycaIn[18][i].r * 0.087929f + + ycaIn[20][i].r * -0.043159f + + ycaIn[22][i].r * 0.019597f + + ycaIn[24][i].r * -0.007540f + + ycaIn[26][i].r * 0.002128f; + + ycaOut[i].b = ycaIn[ 0][i].b * 0.002128f + + ycaIn[ 2][i].b * -0.007540f + + ycaIn[ 4][i].b * 0.019597f + + ycaIn[ 6][i].b * -0.043159f + + ycaIn[ 8][i].b * 0.087929f + + ycaIn[10][i].b * -0.186077f + + ycaIn[12][i].b * 0.627123f + + ycaIn[14][i].b * 0.627123f + + ycaIn[16][i].b * -0.186077f + + ycaIn[18][i].b * 0.087929f + + ycaIn[20][i].b * -0.043159f + + ycaIn[22][i].b * 0.019597f + + ycaIn[24][i].b * -0.007540f + + ycaIn[26][i].b * 0.002128f; + + ycaOut[i].g = ycaIn[13][i].g; + ycaOut[i].a = ycaIn[13][i].a; } } - + void -YCAtoRGBA (const Imath::V3f &yw, - int n, - const Rgba ycaIn[/*n*/], - Rgba rgbaOut[/*n*/]) +YCAtoRGBA (const IMATH_NAMESPACE::V3f &yw, + int n, + const Rgba ycaIn[/*n*/], + Rgba rgbaOut[/*n*/]) { for (int i = 0; i < n; ++i) { - const Rgba &in = ycaIn[i]; - Rgba &out = rgbaOut[i]; - - if (in.r == 0 && in.b == 0) - { - // - // Special case -- both chroma channels are 0. To avoid - // rounding errors, we explicitly set the output R, G and B - // channels equal to the input luminance. - // - // The special cases here and in RGBAtoYCA() ensure that - // converting black-and white images from RGBA to YCA and - // back is lossless. - // - - out.r = in.g; - out.g = in.g; - out.b = in.g; - out.a = in.a; - } - else - { - float Y = in.g; - float r = (in.r + 1) * Y; - float b = (in.b + 1) * Y; - float g = (Y - r * yw.x - b * yw.z) / yw.y; - - out.r = r; - out.g = g; - out.b = b; - out.a = in.a; - } + const Rgba &in = ycaIn[i]; + Rgba &out = rgbaOut[i]; + + if (in.r == 0 && in.b == 0) + { + // + // Special case -- both chroma channels are 0. To avoid + // rounding errors, we explicitly set the output R, G and B + // channels equal to the input luminance. + // + // The special cases here and in RGBAtoYCA() ensure that + // converting black-and white images from RGBA to YCA and + // back is lossless. + // + + out.r = in.g; + out.g = in.g; + out.b = in.g; + out.a = in.a; + } + else + { + float Y = in.g; + float r = (in.r + 1) * Y; + float b = (in.b + 1) * Y; + float g = (Y - r * yw.x - b * yw.z) / yw.y; + + out.r = r; + out.g = g; + out.b = b; + out.a = in.a; + } } } @@ -406,9 +408,9 @@ saturation (const Rgba &in) float rgbMin = min (in.r, min (in.g, in.b)); if (rgbMax > 0) - return 1 - rgbMin / rgbMax; + return 1 - rgbMin / rgbMax; else - return 0; + return 0; } @@ -427,20 +429,20 @@ desaturate (const Rgba &in, float f, const V3f &yw, Rgba &out) if (Yout > 0) { - out.r *= Yin / Yout; - out.g *= Yin / Yout; - out.b *= Yin / Yout; + out.r *= Yin / Yout; + out.g *= Yin / Yout; + out.b *= Yin / Yout; } } } // namespace - + void -fixSaturation (const Imath::V3f &yw, - int n, - const Rgba * const rgbaIn[3], - Rgba rgbaOut[/*n*/]) +fixSaturation (const IMATH_NAMESPACE::V3f &yw, + int n, + const Rgba * const rgbaIn[3], + Rgba rgbaOut[/*n*/]) { float neighborA2 = saturation (rgbaIn[0][0]); float neighborA1 = neighborA2; @@ -450,46 +452,46 @@ fixSaturation (const Imath::V3f &yw, for (int i = 0; i < n; ++i) { - float neighborA0 = neighborA1; - neighborA1 = neighborA2; + float neighborA0 = neighborA1; + neighborA1 = neighborA2; - float neighborB0 = neighborB1; - neighborB1 = neighborB2; + float neighborB0 = neighborB1; + neighborB1 = neighborB2; - if (i < n - 1) - { - neighborA2 = saturation (rgbaIn[0][i + 1]); - neighborB2 = saturation (rgbaIn[2][i + 1]); - } + if (i < n - 1) + { + neighborA2 = saturation (rgbaIn[0][i + 1]); + neighborB2 = saturation (rgbaIn[2][i + 1]); + } - // - // A0 A1 A2 - // rgbaOut[i] - // B0 B1 B2 - // + // + // A0 A1 A2 + // rgbaOut[i] + // B0 B1 B2 + // - float sMean = min (1.0f, 0.25f * (neighborA0 + neighborA2 + - neighborB0 + neighborB2)); + float sMean = min (1.0f, 0.25f * (neighborA0 + neighborA2 + + neighborB0 + neighborB2)); - const Rgba &in = rgbaIn[1][i]; - Rgba &out = rgbaOut[i]; + const Rgba &in = rgbaIn[1][i]; + Rgba &out = rgbaOut[i]; - float s = saturation (in); + float s = saturation (in); - if (s > sMean) - { - float sMax = min (1.0f, 1 - (1 - sMean) * 0.25f); + if (s > sMean) + { + float sMax = min (1.0f, 1 - (1 - sMean) * 0.25f); - if (s > sMax) - { - desaturate (in, sMax / s, yw, out); - continue; - } - } + if (s > sMax) + { + desaturate (in, sMax / s, yw, out); + continue; + } + } - out = in; + out = in; } } } // namespace RgbaYca -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfRgbaYca.h b/3rdparty/openexr/IlmImf/ImfRgbaYca.h index 8b894f51d4..c4c6775c52 100644 --- a/3rdparty/openexr/IlmImf/ImfRgbaYca.h +++ b/3rdparty/openexr/IlmImf/ImfRgbaYca.h @@ -83,24 +83,24 @@ // Next, decimateChomaHoriz() eliminates the chroma values from // the odd-numbered pixels in every scan line: // -// YCA YA YCA YA ... YCA YA -// YCA YA YCA YA ... YCA YA -// YCA YA YCA YA ... YCA YA -// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA // ... -// YCA YA YCA YA ... YCA YA -// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA +// YCA YA YCA YA ... YCA YA // // decimateChromaVert() eliminates all chroma values from the // odd-numbered scan lines: // -// YCA YA YCA YA ... YCA YA -// YA YA YA YA ... YA YA -// YCA YA YCA YA ... YCA YA -// YA YA YA YA ... YA YA +// YCA YA YCA YA ... YCA YA +// YA YA YA YA ... YA YA +// YCA YA YCA YA ... YCA YA +// YA YA YA YA ... YA YA // ... -// YCA YA YCA YA ... YCA YA -// YA YA YA YA ... YA YA +// YCA YA YCA YA ... YCA YA +// YA YA YA YA ... YA YA // // Finally, roundYCA() reduces the precision of the luminance // and chroma values so that the pixel data shrink more when @@ -114,10 +114,12 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfRgba.h" +#include "ImfChromaticities.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { namespace RgbaYca { @@ -133,8 +135,9 @@ static const int N2 = N / 2; // Convert a set of primary chromaticities into a set of weighting // factors for computing a pixels's luminance, Y, from R, G and B // - -Imath::V3f computeYw (const Chromaticities &cr); + +IMF_EXPORT +IMATH_NAMESPACE::V3f computeYw (const Chromaticities &cr); // @@ -148,11 +151,12 @@ Imath::V3f computeYw (const Chromaticities &cr); // yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). // -void RGBAtoYCA (const Imath::V3f &yw, - int n, - bool aIsValid, - const Rgba rgbaIn[/*n*/], - Rgba ycaOut[/*n*/]); +IMF_EXPORT +void RGBAtoYCA (const IMATH_NAMESPACE::V3f &yw, + int n, + bool aIsValid, + const Rgba rgbaIn[/*n*/], + Rgba ycaOut[/*n*/]); // // Perform horizontal low-pass filtering and subsampling of @@ -164,9 +168,10 @@ void RGBAtoYCA (const Imath::V3f &yw, // "real" input pixel. // +IMF_EXPORT void decimateChromaHoriz (int n, - const Rgba ycaIn[/*n+N-1*/], - Rgba ycaOut[/*n*/]); + const Rgba ycaIn[/*n+N-1*/], + Rgba ycaOut[/*n*/]); // // Perform vertical chroma channel low-pass filtering and subsampling. @@ -174,9 +179,10 @@ void decimateChromaHoriz (int n, // of output pixels. // +IMF_EXPORT void decimateChromaVert (int n, - const Rgba * const ycaIn[N], - Rgba ycaOut[/*n*/]); + const Rgba * const ycaIn[N], + Rgba ycaOut[/*n*/]); // // Round the luminance and chroma channels of an array of YCA @@ -185,41 +191,45 @@ void decimateChromaVert (int n, // are rounded to roundY and roundC bits respectively. // +IMF_EXPORT void roundYCA (int n, - unsigned int roundY, - unsigned int roundC, - const Rgba ycaIn[/*n*/], - Rgba ycaOut[/*n*/]); + unsigned int roundY, + unsigned int roundC, + const Rgba ycaIn[/*n*/], + Rgba ycaOut[/*n*/]); // // For a scan line that has valid chroma data only for every other pixel, // reconstruct the missing chroma values. // +IMF_EXPORT void reconstructChromaHoriz (int n, - const Rgba ycaIn[/*n+N-1*/], - Rgba ycaOut[/*n*/]); + const Rgba ycaIn[/*n+N-1*/], + Rgba ycaOut[/*n*/]); // // For a scan line that has only luminance and no valid chroma data, // reconstruct chroma from the surronding N scan lines. // +IMF_EXPORT void reconstructChromaVert (int n, - const Rgba * const ycaIn[N], - Rgba ycaOut[/*n*/]); - + const Rgba * const ycaIn[N], + Rgba ycaOut[/*n*/]); + // // Convert an array of n YCA (luminance/chroma/alpha) pixels to RGBA. // This function is the inverse of RGBAtoYCA(). // yw is a set of RGB-to-Y weighting factors, as computed by computeYw(). // -void YCAtoRGBA (const Imath::V3f &yw, - int n, - const Rgba ycaIn[/*n*/], - Rgba rgbaOut[/*n*/]); - +IMF_EXPORT +void YCAtoRGBA (const IMATH_NAMESPACE::V3f &yw, + int n, + const Rgba ycaIn[/*n*/], + Rgba rgbaOut[/*n*/]); + // // Eliminate super-saturated pixels: // @@ -237,12 +247,13 @@ void YCAtoRGBA (const Imath::V3f &yw, // saturation of rgbaIn[1], and stores the result in rgbaOut. // -void fixSaturation (const Imath::V3f &yw, - int n, - const Rgba * const rgbaIn[3], - Rgba rgbaOut[/*n*/]); +IMF_EXPORT +void fixSaturation (const IMATH_NAMESPACE::V3f &yw, + int n, + const Rgba * const rgbaIn[3], + Rgba rgbaOut[/*n*/]); } // namespace RgbaYca -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfRle.cpp b/3rdparty/openexr/IlmImf/ImfRle.cpp new file mode 100644 index 0000000000..7be6ac44ae --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfRle.cpp @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include +#include "ImfRle.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +namespace { + +const int MIN_RUN_LENGTH = 3; +const int MAX_RUN_LENGTH = 127; + +} + +// +// Compress an array of bytes, using run-length encoding, +// and return the length of the compressed data. +// + +int +rleCompress (int inLength, const char in[], signed char out[]) +{ + const char *inEnd = in + inLength; + const char *runStart = in; + const char *runEnd = in + 1; + signed char *outWrite = out; + + while (runStart < inEnd) + { + while (runEnd < inEnd && + *runStart == *runEnd && + runEnd - runStart - 1 < MAX_RUN_LENGTH) + { + ++runEnd; + } + + if (runEnd - runStart >= MIN_RUN_LENGTH) + { + // + // Compressable run + // + + *outWrite++ = (runEnd - runStart) - 1; + *outWrite++ = *(signed char *) runStart; + runStart = runEnd; + } + else + { + // + // Uncompressable run + // + + while (runEnd < inEnd && + ((runEnd + 1 >= inEnd || + *runEnd != *(runEnd + 1)) || + (runEnd + 2 >= inEnd || + *(runEnd + 1) != *(runEnd + 2))) && + runEnd - runStart < MAX_RUN_LENGTH) + { + ++runEnd; + } + + *outWrite++ = runStart - runEnd; + + while (runStart < runEnd) + { + *outWrite++ = *(signed char *) (runStart++); + } + } + + ++runEnd; + } + + return outWrite - out; +} + + +// +// Uncompress an array of bytes compressed with rleCompress(). +// Returns the length of the oncompressed data, or 0 if the +// length of the uncompressed data would be more than maxLength. +// + +int +rleUncompress (int inLength, int maxLength, const signed char in[], char out[]) +{ + char *outStart = out; + + while (inLength > 0) + { + if (*in < 0) + { + int count = -((int)*in++); + inLength -= count + 1; + + if (0 > (maxLength -= count)) + return 0; + + memcpy(out, in, count); + out += count; + in += count; + } + else + { + int count = *in++; + inLength -= 2; + + if (0 > (maxLength -= count + 1)) + return 0; + + memset(out, *(char*)in, count+1); + out += count+1; + + in++; + } + } + + return out - outStart; +} + + + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfRle.h b/3rdparty/openexr/IlmImf/ImfRle.h new file mode 100644 index 0000000000..0def33654d --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfRle.h @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMF_RLE_H_ +#define INCLUDED_IMF_RLE_H_ + +#include "ImfNamespace.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Compress an array of bytes, using run-length encoding, +// and return the length of the compressed data. +// + +IMF_EXPORT +int rleCompress (int inLength, const char in[], signed char out[]); + +// +// Uncompress an array of bytes compressed with rleCompress(). +// Returns the length of the uncompressed data, or 0 if the +// length of the uncompressed data would be more than maxLength. +// + +IMF_EXPORT +int rleUncompress (int inLength, int maxLength, + const signed char in[], char out[]); + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfRleCompressor.cpp b/3rdparty/openexr/IlmImf/ImfRleCompressor.cpp index e214a4e0d0..33914e8d19 100644 --- a/3rdparty/openexr/IlmImf/ImfRleCompressor.cpp +++ b/3rdparty/openexr/IlmImf/ImfRleCompressor.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -40,124 +40,13 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfRleCompressor.h" +#include "ImfCheckedArithmetic.h" +#include "ImfRle.h" #include "Iex.h" +#include "ImfNamespace.h" -namespace Imf { -namespace { - -const int MIN_RUN_LENGTH = 3; -const int MAX_RUN_LENGTH = 127; - - -// -// Compress an array of bytes, using run-length encoding, -// and return the length of the compressed data. -// - -int -rleCompress (int inLength, const char in[], signed char out[]) -{ - const char *inEnd = in + inLength; - const char *runStart = in; - const char *runEnd = in + 1; - signed char *outWrite = out; - - while (runStart < inEnd) - { - while (runEnd < inEnd && - *runStart == *runEnd && - runEnd - runStart - 1 < MAX_RUN_LENGTH) - { - ++runEnd; - } - - if (runEnd - runStart >= MIN_RUN_LENGTH) - { - // - // Compressable run - // - - *outWrite++ = (runEnd - runStart) - 1; - *outWrite++ = *(signed char *) runStart; - runStart = runEnd; - } - else - { - // - // Uncompressable run - // - - while (runEnd < inEnd && - ((runEnd + 1 >= inEnd || - *runEnd != *(runEnd + 1)) || - (runEnd + 2 >= inEnd || - *(runEnd + 1) != *(runEnd + 2))) && - runEnd - runStart < MAX_RUN_LENGTH) - { - ++runEnd; - } - - *outWrite++ = runStart - runEnd; - - while (runStart < runEnd) - { - *outWrite++ = *(signed char *) (runStart++); - } - } - - ++runEnd; - } - - return outWrite - out; -} - - -// -// Uncompress an array of bytes compressed with rleCompress(). -// Returns the length of the oncompressed data, or 0 if the -// length of the uncompressed data would be more than maxLength. -// - -int -rleUncompress (int inLength, int maxLength, const signed char in[], char out[]) -{ - char *outStart = out; - - while (inLength > 0) - { - if (*in < 0) - { - int count = -((int)*in++); - inLength -= count + 1; - - if (0 > (maxLength -= count)) - return 0; - - while (count-- > 0) - *out++ = *(char *) (in++); - } - else - { - int count = *in++; - inLength -= 2; - - if (0 > (maxLength -= count + 1)) - return 0; - - while (count-- >= 0) - *out++ = *(char *) in; - - in++; - } - } - - return out - outStart; -} - -} // namespace - +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER RleCompressor::RleCompressor (const Header &hdr, size_t maxScanLineSize): Compressor (hdr), @@ -190,18 +79,18 @@ RleCompressor::numScanLines () const int RleCompressor::compress (const char *inPtr, - int inSize, - int /*minY*/, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { // - // Special case ­- empty input buffer + // Special case ďż˝- empty input buffer // if (inSize == 0) { - outPtr = _outBuffer; - return 0; + outPtr = _outBuffer; + return 0; } // @@ -209,22 +98,22 @@ RleCompressor::compress (const char *inPtr, // { - char *t1 = _tmpBuffer; - char *t2 = _tmpBuffer + (inSize + 1) / 2; - const char *stop = inPtr + inSize; + char *t1 = _tmpBuffer; + char *t2 = _tmpBuffer + (inSize + 1) / 2; + const char *stop = inPtr + inSize; - while (true) - { - if (inPtr < stop) - *(t1++) = *(inPtr++); - else - break; - - if (inPtr < stop) - *(t2++) = *(inPtr++); - else - break; - } + while (true) + { + if (inPtr < stop) + *(t1++) = *(inPtr++); + else + break; + + if (inPtr < stop) + *(t2++) = *(inPtr++); + else + break; + } } // @@ -232,17 +121,17 @@ RleCompressor::compress (const char *inPtr, // { - unsigned char *t = (unsigned char *) _tmpBuffer + 1; - unsigned char *stop = (unsigned char *) _tmpBuffer + inSize; - int p = t[-1]; + unsigned char *t = (unsigned char *) _tmpBuffer + 1; + unsigned char *stop = (unsigned char *) _tmpBuffer + inSize; + int p = t[-1]; - while (t < stop) - { - int d = int (t[0]) - p + (128 + 256); - p = t[0]; - t[0] = d; - ++t; - } + while (t < stop) + { + int d = int (t[0]) - p + (128 + 256); + p = t[0]; + t[0] = d; + ++t; + } } // @@ -256,18 +145,18 @@ RleCompressor::compress (const char *inPtr, int RleCompressor::uncompress (const char *inPtr, - int inSize, - int /*minY*/, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { // - // Special case ­- empty input buffer + // Special case ďż˝- empty input buffer // if (inSize == 0) { - outPtr = _outBuffer; - return 0; + outPtr = _outBuffer; + return 0; } // @@ -277,10 +166,10 @@ RleCompressor::uncompress (const char *inPtr, int outSize; if (0 == (outSize = rleUncompress (inSize, _maxScanLineSize, - (const signed char *) inPtr, - _tmpBuffer))) + (const signed char *) inPtr, + _tmpBuffer))) { - throw Iex::InputExc ("Data decoding (rle) failed."); + throw IEX_NAMESPACE::InputExc ("Data decoding (rle) failed."); } // @@ -288,15 +177,15 @@ RleCompressor::uncompress (const char *inPtr, // { - unsigned char *t = (unsigned char *) _tmpBuffer + 1; - unsigned char *stop = (unsigned char *) _tmpBuffer + outSize; + unsigned char *t = (unsigned char *) _tmpBuffer + 1; + unsigned char *stop = (unsigned char *) _tmpBuffer + outSize; - while (t < stop) - { - int d = int (t[-1]) + int (t[0]) - 128; - t[0] = d; - ++t; - } + while (t < stop) + { + int d = int (t[-1]) + int (t[0]) - 128; + t[0] = d; + ++t; + } } // @@ -304,23 +193,23 @@ RleCompressor::uncompress (const char *inPtr, // { - const char *t1 = _tmpBuffer; - const char *t2 = _tmpBuffer + (outSize + 1) / 2; - char *s = _outBuffer; - char *stop = s + outSize; + const char *t1 = _tmpBuffer; + const char *t2 = _tmpBuffer + (outSize + 1) / 2; + char *s = _outBuffer; + char *stop = s + outSize; - while (true) - { - if (s < stop) - *(s++) = *(t1++); - else - break; - - if (s < stop) - *(s++) = *(t2++); - else - break; - } + while (true) + { + if (s < stop) + *(s++) = *(t1++); + else + break; + + if (s < stop) + *(s++) = *(t2++); + else + break; + } } outPtr = _outBuffer; @@ -328,4 +217,4 @@ RleCompressor::uncompress (const char *inPtr, } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfRleCompressor.h b/3rdparty/openexr/IlmImf/ImfRleCompressor.h index 0bec2e272a..7bb253abb7 100644 --- a/3rdparty/openexr/IlmImf/ImfRleCompressor.h +++ b/3rdparty/openexr/IlmImf/ImfRleCompressor.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,29 +43,35 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfCompressor.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class RleCompressor: public Compressor { public: + IMF_EXPORT RleCompressor (const Header &hdr, size_t maxScanLineSize); + IMF_EXPORT virtual ~RleCompressor (); + IMF_EXPORT virtual int numScanLines () const; + IMF_EXPORT virtual int compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); + int inSize, + int minY, + const char *&outPtr); + IMF_EXPORT virtual int uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); + int inSize, + int minY, + const char *&outPtr); private: int _maxScanLineSize; @@ -74,6 +80,6 @@ class RleCompressor: public Compressor }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp index 5d8b52201b..c3eadb7941 100644 --- a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,42 +39,50 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include +#include "ImfScanLineInputFile.h" +#include "ImfChannelList.h" +#include "ImfMisc.h" +#include "ImfStdIO.h" +#include "ImfCompressor.h" #include "ImathBox.h" #include "ImathFun.h" #include #include #include +#include #include "IlmThreadPool.h" #include "IlmThreadSemaphore.h" #include "IlmThreadMutex.h" #include "Iex.h" +#include "ImfVersion.h" +#include "ImfOptimizedPixelReading.h" +#include "ImfNamespace.h" +#include "ImfStandardAttributes.h" + +#include #include #include #include -#include // for std::max() +#include +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { -using Imath::Box2i; -using Imath::divp; -using Imath::modp; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::divp; +using IMATH_NAMESPACE::modp; using std::string; using std::vector; using std::ifstream; using std::min; using std::max; -using IlmThread::Mutex; -using IlmThread::Lock; -using IlmThread::Semaphore; -using IlmThread::Task; -using IlmThread::TaskGroup; -using IlmThread::ThreadPool; +using std::sort; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using ILMTHREAD_NAMESPACE::Semaphore; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; namespace { @@ -92,25 +100,25 @@ struct InSliceInfo double fillValue; InSliceInfo (PixelType typeInFrameBuffer = HALF, - PixelType typeInFile = HALF, - char *base = 0, - size_t xStride = 0, - size_t yStride = 0, - int xSampling = 1, - int ySampling = 1, - bool fill = false, - bool skip = false, - double fillValue = 0.0); + PixelType typeInFile = HALF, + char *base = 0, + size_t xStride = 0, + size_t yStride = 0, + int xSampling = 1, + int ySampling = 1, + bool fill = false, + bool skip = false, + double fillValue = 0.0); }; InSliceInfo::InSliceInfo (PixelType tifb, - PixelType tifl, - char *b, - size_t xs, size_t ys, - int xsm, int ysm, - bool f, bool s, - double fv) + PixelType tifl, + char *b, + size_t xs, size_t ys, + int xsm, int ysm, + bool f, bool s, + double fv) : typeInFrameBuffer (tifb), typeInFile (tifl), @@ -172,6 +180,29 @@ LineBuffer::~LineBuffer () delete compressor; } +/// helper struct used to detect the order that the channels are stored + +struct sliceOptimizationData +{ + const char * base; ///< pointer to pixel data + bool fill; ///< is this channel being filled with constant, instead of read? + half fillValue; ///< if filling, the value to use + size_t offset; ///< position this channel will be in the read buffer, accounting for previous channels, as well as their type + PixelType type; ///< type of channel + size_t xStride; ///< x-stride of channel in buffer (must be set to cause channels to interleave) + size_t yStride; ///< y-stride of channel in buffer (must be same in all channels, else order will change, which is bad) + int xSampling; ///< channel x sampling + int ySampling; ///< channel y sampling + + + /// we need to keep the list sorted in the order they'll be written to memory + bool operator<(const sliceOptimizationData& other ) const + { + return base < other.base; + } +}; + + } // namespace @@ -186,33 +217,40 @@ struct ScanLineInputFile::Data: public Mutex int minY; // data window's min y coord int maxY; // data window's max x coord vector lineOffsets; // stores offsets in file for - // each line + // each line bool fileIsComplete; // True if no scanlines are missing - // in the file + // in the file int nextLineBufferMinY; // minimum y of the next linebuffer vector bytesPerLine; // combined size of a line over all // channels vector offsetInLineBuffer; // offset for each scanline in its // linebuffer vector slices; // info about channels in file - IStream * is; // file stream to read from - + vector lineBuffers; // each holds one line buffer int linesInBuffer; // number of scanlines each buffer // holds size_t lineBufferSize; // size of the line buffer + int partNumber; // part number - Data (IStream *is, int numThreads); + bool memoryMapped; // if the stream is memory mapped + OptimizationMode optimizationMode; // optimizibility of the input file + vector optimizationData; ///< channel ordering for optimized reading + + Data (int numThreads); ~Data (); - + inline LineBuffer * getLineBuffer (int number); // hash function from line - // buffer indices into our - // vector of line buffers + // buffer indices into our + // vector of line buffers + + }; -ScanLineInputFile::Data::Data (IStream *is, int numThreads): - is (is) +ScanLineInputFile::Data::Data (int numThreads): + partNumber(-1), + memoryMapped(false) { // // We need at least one lineBuffer, but if threading is used, @@ -241,40 +279,40 @@ namespace { void -reconstructLineOffsets (IStream &is, - LineOrder lineOrder, - vector &lineOffsets) +reconstructLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + LineOrder lineOrder, + vector &lineOffsets) { Int64 position = is.tellg(); try { - for (unsigned int i = 0; i < lineOffsets.size(); i++) - { - Int64 lineOffset = is.tellg(); + for (unsigned int i = 0; i < lineOffsets.size(); i++) + { + Int64 lineOffset = is.tellg(); - int y; - Xdr::read (is, y); + int y; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, y); - int dataSize; - Xdr::read (is, dataSize); + int dataSize; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, dataSize); - Xdr::skip (is, dataSize); + Xdr::skip (is, dataSize); - if (lineOrder == INCREASING_Y) - lineOffsets[i] = lineOffset; - else - lineOffsets[lineOffsets.size() - i - 1] = lineOffset; - } + if (lineOrder == INCREASING_Y) + lineOffsets[i] = lineOffset; + else + lineOffsets[lineOffsets.size() - i - 1] = lineOffset; + } } catch (...) { - // - // Suppress all exceptions. This functions is - // called only to reconstruct the line offset - // table for incomplete files, and exceptions - // are likely. - // + // + // Suppress all exceptions. This functions is + // called only to reconstruct the line offset + // table for incomplete files, and exceptions + // are likely. + // } is.clear(); @@ -283,48 +321,49 @@ reconstructLineOffsets (IStream &is, void -readLineOffsets (IStream &is, - LineOrder lineOrder, - vector &lineOffsets, - bool &complete) +readLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + LineOrder lineOrder, + vector &lineOffsets, + bool &complete) { for (unsigned int i = 0; i < lineOffsets.size(); i++) { - Xdr::read (is, lineOffsets[i]); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, lineOffsets[i]); } complete = true; for (unsigned int i = 0; i < lineOffsets.size(); i++) { - if (lineOffsets[i] <= 0) - { - // - // Invalid data in the line offset table mean that - // the file is probably incomplete (the table is - // the last thing written to the file). Either - // some process is still busy writing the file, - // or writing the file was aborted. - // - // We should still be able to read the existing - // parts of the file. In order to do this, we - // have to make a sequential scan over the scan - // line data to reconstruct the line offset table. - // - - complete = false; - reconstructLineOffsets (is, lineOrder, lineOffsets); - break; - } + if (lineOffsets[i] <= 0) + { + // + // Invalid data in the line offset table mean that + // the file is probably incomplete (the table is + // the last thing written to the file). Either + // some process is still busy writing the file, + // or writing the file was aborted. + // + // We should still be able to read the existing + // parts of the file. In order to do this, we + // have to make a sequential scan over the scan + // line data to reconstruct the line offset table. + // + + complete = false; + reconstructLineOffsets (is, lineOrder, lineOffsets); + break; + } } } void -readPixelData (ScanLineInputFile::Data *ifd, - int minY, - char *&buffer, - int &dataSize) +readPixelData (InputStreamMutex *streamData, + ScanLineInputFile::Data *ifd, + int minY, + char *&buffer, + int &dataSize) { // // Read a single line buffer from the input file. @@ -335,19 +374,34 @@ readPixelData (ScanLineInputFile::Data *ifd, // array (hence buffer needs to be a reference to a char *). // - Int64 lineOffset = - ifd->lineOffsets[(minY - ifd->minY) / ifd->linesInBuffer]; + int lineBufferNumber = (minY - ifd->minY) / ifd->linesInBuffer; + if (lineBufferNumber < 0 || lineBufferNumber >= int(ifd->lineOffsets.size())) + THROW (IEX_NAMESPACE::InputExc, "Invalid scan line " << minY << " requested or missing."); + + Int64 lineOffset = ifd->lineOffsets[lineBufferNumber]; if (lineOffset == 0) - THROW (Iex::InputExc, "Scan line " << minY << " is missing."); + THROW (IEX_NAMESPACE::InputExc, "Scan line " << minY << " is missing."); // // Seek to the start of the scan line in the file, // if necessary. // - if (ifd->nextLineBufferMinY != minY) - ifd->is->seekg (lineOffset); + if ( !isMultiPart(ifd->version) ) + { + if (ifd->nextLineBufferMinY != minY) + streamData->is->seekg (lineOffset); + } + else + { + // + // In a multi-part file, the file pointer may have been moved by + // other parts, so we have to ask tellg() where we are. + // + if (streamData->is->tellg() != ifd->lineOffsets[lineBufferNumber]) + streamData->is->seekg (lineOffset); + } // // Read the data block's header. @@ -355,23 +409,37 @@ readPixelData (ScanLineInputFile::Data *ifd, int yInFile; - Xdr::read (*ifd->is, yInFile); - Xdr::read (*ifd->is, dataSize); + // + // Read the part number when we are dealing with a multi-part file. + // + if (isMultiPart(ifd->version)) + { + int partNumber; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, partNumber); + if (partNumber != ifd->partNumber) + { + THROW (IEX_NAMESPACE::ArgExc, "Unexpected part number " << partNumber + << ", should be " << ifd->partNumber << "."); + } + } + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, yInFile); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, dataSize); + if (yInFile != minY) - throw Iex::InputExc ("Unexpected data block y coordinate."); + throw IEX_NAMESPACE::InputExc ("Unexpected data block y coordinate."); if (dataSize > (int) ifd->lineBufferSize) - throw Iex::InputExc ("Unexpected data block length."); + throw IEX_NAMESPACE::InputExc ("Unexpected data block length."); // // Read the pixel data. // - if (ifd->is->isMemoryMapped ()) - buffer = ifd->is->readMemoryMapped (dataSize); + if (streamData->is->isMemoryMapped ()) + buffer = streamData->is->readMemoryMapped (dataSize); else - ifd->is->read (buffer, dataSize); + streamData->is->read (buffer, dataSize); // // Keep track of which scan line is the next one in @@ -380,11 +448,12 @@ readPixelData (ScanLineInputFile::Data *ifd, // if (ifd->lineOrder == INCREASING_Y) - ifd->nextLineBufferMinY = minY + ifd->linesInBuffer; + ifd->nextLineBufferMinY = minY + ifd->linesInBuffer; else - ifd->nextLineBufferMinY = minY - ifd->linesInBuffer; + ifd->nextLineBufferMinY = minY - ifd->linesInBuffer; } + // // A LineBufferTask encapsulates the task uncompressing a set of @@ -397,9 +466,10 @@ class LineBufferTask : public Task LineBufferTask (TaskGroup *group, ScanLineInputFile::Data *ifd, - LineBuffer *lineBuffer, + LineBuffer *lineBuffer, int scanLineMin, - int scanLineMax); + int scanLineMax, + OptimizationMode optimizationMode); virtual ~LineBufferTask (); @@ -411,6 +481,7 @@ class LineBufferTask : public Task LineBuffer * _lineBuffer; int _scanLineMin; int _scanLineMax; + OptimizationMode _optimizationMode; }; @@ -419,13 +490,14 @@ LineBufferTask::LineBufferTask ScanLineInputFile::Data *ifd, LineBuffer *lineBuffer, int scanLineMin, - int scanLineMax) + int scanLineMax,OptimizationMode optimizationMode) : Task (group), _ifd (ifd), _lineBuffer (lineBuffer), _scanLineMin (scanLineMin), - _scanLineMax (scanLineMax) + _scanLineMax (scanLineMax), + _optimizationMode(optimizationMode) { // empty } @@ -449,27 +521,29 @@ LineBufferTask::execute () // // Uncompress the data, if necessary // - + if (_lineBuffer->uncompressedData == 0) { int uncompressedSize = 0; int maxY = min (_lineBuffer->maxY, _ifd->maxY); - + for (int i = _lineBuffer->minY - _ifd->minY; i <= maxY - _ifd->minY; - ++i) - { + ++i) + { uncompressedSize += (int) _ifd->bytesPerLine[i]; - } - + } + if (_lineBuffer->compressor && _lineBuffer->dataSize < uncompressedSize) { _lineBuffer->format = _lineBuffer->compressor->format(); _lineBuffer->dataSize = _lineBuffer->compressor->uncompress - (_lineBuffer->buffer, _lineBuffer->dataSize, - _lineBuffer->minY, _lineBuffer->uncompressedData); + (_lineBuffer->buffer, + _lineBuffer->dataSize, + _lineBuffer->minY, + _lineBuffer->uncompressedData); } else { @@ -477,12 +551,12 @@ LineBufferTask::execute () // If the line is uncompressed, it's in XDR format, // regardless of the compressor's output format. // - + _lineBuffer->format = Compressor::XDR; _lineBuffer->uncompressedData = _lineBuffer->buffer; } } - + int yStart, yStop, dy; if (_ifd->lineOrder == INCREASING_Y) @@ -497,7 +571,7 @@ LineBufferTask::execute () yStop = _scanLineMin - 1; dy = -1; } - + for (int y = yStart; y != yStop; y += dy) { // @@ -505,46 +579,46 @@ LineBufferTask::execute () // from the machine-independent representation, and // store the result in the frame buffer. // - + const char *readPtr = _lineBuffer->uncompressedData + _ifd->offsetInLineBuffer[y - _ifd->minY]; - + // // Iterate over all image channels. // - + for (unsigned int i = 0; i < _ifd->slices.size(); ++i) { // // Test if scan line y of this channel contains any data - // (the scan line contains data only if y % ySampling == 0). + // (the scan line contains data only if y % ySampling == 0). // - + const InSliceInfo &slice = _ifd->slices[i]; - + if (modp (y, slice.ySampling) != 0) continue; - + // // Find the x coordinates of the leftmost and rightmost // sampled pixels (i.e. pixels within the data window // for which x % xSampling == 0). // - + int dMinX = divp (_ifd->minX, slice.xSampling); int dMaxX = divp (_ifd->maxX, slice.xSampling); - + // - // Fill the frame buffer with pixel data. + // Fill the frame buffer with pixel data. // - + if (slice.skip) { // // The file contains data for this channel, but // the frame buffer contains no slice for this channel. // - + skipChannel (readPtr, slice.typeInFile, dMaxX - dMinX + 1); } else @@ -552,14 +626,14 @@ LineBufferTask::execute () // // The frame buffer contains a slice for this channel. // - + char *linePtr = slice.base + divp (y, slice.ySampling) * slice.yStride; - + char *writePtr = linePtr + dMinX * slice.xStride; char *endPtr = linePtr + dMaxX * slice.xStride; - + copyIntoFrameBuffer (readPtr, writePtr, endPtr, slice.xStride, slice.fill, slice.fillValue, _lineBuffer->format, @@ -588,98 +662,456 @@ LineBufferTask::execute () } -LineBufferTask * -newLineBufferTask +#ifdef IMF_HAVE_SSE2 +// +// IIF format is more restricted than a perfectly generic one, +// so it is possible to perform some optimizations. +// +class LineBufferTaskIIF : public Task +{ + public: + + LineBufferTaskIIF (TaskGroup *group, + ScanLineInputFile::Data *ifd, + LineBuffer *lineBuffer, + int scanLineMin, + int scanLineMax, + OptimizationMode optimizationMode); + + virtual ~LineBufferTaskIIF (); + + virtual void execute (); + + template + void getWritePointer (int y, + unsigned short*& pOutWritePointerRight, + size_t& outPixelsToCopySSE, + size_t& outPixelsToCopyNormal,int bank=0) const; + + template + void getWritePointerStereo (int y, + unsigned short*& outWritePointerRight, + unsigned short*& outWritePointerLeft, + size_t& outPixelsToCopySSE, + size_t& outPixelsToCopyNormal) const; + + private: + + ScanLineInputFile::Data * _ifd; + LineBuffer * _lineBuffer; + int _scanLineMin; + int _scanLineMax; + OptimizationMode _optimizationMode; + +}; + +LineBufferTaskIIF::LineBufferTaskIIF (TaskGroup *group, ScanLineInputFile::Data *ifd, - int number, + LineBuffer *lineBuffer, int scanLineMin, - int scanLineMax) + int scanLineMax, + OptimizationMode optimizationMode + ) + : + Task (group), + _ifd (ifd), + _lineBuffer (lineBuffer), + _scanLineMin (scanLineMin), + _scanLineMax (scanLineMax), + _optimizationMode (optimizationMode) { - // - // Wait for a line buffer to become available, fill the line - // buffer with raw data from the file if necessary, and create - // a new LineBufferTask whose execute() method will uncompress - // the contents of the buffer and copy the pixels into the - // frame buffer. - // + /* + // + // indicates the optimised path has been taken + // + static bool could_optimise=false; + if(could_optimise==false) + { + std::cerr << " optimised path\n"; + could_optimise=true; + } + */ +} + +LineBufferTaskIIF::~LineBufferTaskIIF () +{ + // + // Signal that the line buffer is now free + // + + _lineBuffer->post (); +} + +// Return 0 if we are to skip because of sampling +// channelBank is 0 for the first group of channels, 1 for the second +template +void LineBufferTaskIIF::getWritePointer + (int y, + unsigned short*& outWritePointerRight, + size_t& outPixelsToCopySSE, + size_t& outPixelsToCopyNormal, + int channelBank + ) const +{ + // Channels are saved alphabetically, so the order is B G R. + // The last slice (R) will give us the location of our write pointer. + // The only slice that we support skipping is alpha, i.e. the first one. + // This does not impact the write pointer or the pixels to copy at all. + + size_t nbSlicesInBank = _ifd->optimizationData.size(); + + int sizeOfSingleValue = sizeof(TYPE); + + if(_ifd->optimizationData.size()>4) + { + // there are two banks - we only copy one at once + nbSlicesInBank/=2; + } + + + size_t firstChannel = 0; + if(channelBank==1) + { + firstChannel = _ifd->optimizationData.size()/2; + } + + sliceOptimizationData& firstSlice = _ifd->optimizationData[firstChannel]; + + if (modp (y, firstSlice.ySampling) != 0) + { + outPixelsToCopySSE = 0; + outPixelsToCopyNormal = 0; + outWritePointerRight = 0; + } + + const char* linePtr1 = firstSlice.base + + divp (y, firstSlice.ySampling) * + firstSlice.yStride; + + int dMinX1 = divp (_ifd->minX, firstSlice.xSampling); + int dMaxX1 = divp (_ifd->maxX, firstSlice.xSampling); + + // Construct the writePtr so that we start writing at + // linePtr + Min offset in the line. + outWritePointerRight = (unsigned short*)(linePtr1 + + dMinX1 * firstSlice.xStride ); + + size_t bytesToCopy = ((linePtr1 + dMaxX1 * firstSlice.xStride ) - + (linePtr1 + dMinX1 * firstSlice.xStride )) + 2; + size_t shortsToCopy = bytesToCopy / sizeOfSingleValue; + size_t pixelsToCopy = (shortsToCopy / nbSlicesInBank ) + 1; + + // We only support writing to SSE if we have no pixels to copy normally + outPixelsToCopySSE = pixelsToCopy / 8; + outPixelsToCopyNormal = pixelsToCopy % 8; + +} - LineBuffer *lineBuffer = ifd->getLineBuffer (number); - try - { - lineBuffer->wait (); +template +void LineBufferTaskIIF::getWritePointerStereo + (int y, + unsigned short*& outWritePointerRight, + unsigned short*& outWritePointerLeft, + size_t& outPixelsToCopySSE, + size_t& outPixelsToCopyNormal) const +{ + getWritePointer(y,outWritePointerRight,outPixelsToCopySSE,outPixelsToCopyNormal,0); + + + if(outWritePointerRight) + { + getWritePointer(y,outWritePointerLeft,outPixelsToCopySSE,outPixelsToCopyNormal,1); + } + +} - if (lineBuffer->number != number) +void +LineBufferTaskIIF::execute() +{ + try { - lineBuffer->minY = ifd->minY + number * ifd->linesInBuffer; - lineBuffer->maxY = lineBuffer->minY + ifd->linesInBuffer - 1; - - lineBuffer->number = number; - lineBuffer->uncompressedData = 0; - - readPixelData (ifd, lineBuffer->minY, - lineBuffer->buffer, - lineBuffer->dataSize); - } + // + // Uncompress the data, if necessary + // + + if (_lineBuffer->uncompressedData == 0) + { + int uncompressedSize = 0; + int maxY = min (_lineBuffer->maxY, _ifd->maxY); + + for (int i = _lineBuffer->minY - _ifd->minY; + i <= maxY - _ifd->minY; + ++i) + { + uncompressedSize += (int) _ifd->bytesPerLine[i]; + } + + if (_lineBuffer->compressor && + _lineBuffer->dataSize < uncompressedSize) + { + _lineBuffer->format = _lineBuffer->compressor->format(); + + _lineBuffer->dataSize = + _lineBuffer->compressor->uncompress (_lineBuffer->buffer, + _lineBuffer->dataSize, + _lineBuffer->minY, + _lineBuffer->uncompressedData); + } + else + { + // + // If the line is uncompressed, it's in XDR format, + // regardless of the compressor's output format. + // + + _lineBuffer->format = Compressor::XDR; + _lineBuffer->uncompressedData = _lineBuffer->buffer; + } + } + + int yStart, yStop, dy; + + if (_ifd->lineOrder == INCREASING_Y) + { + yStart = _scanLineMin; + yStop = _scanLineMax + 1; + dy = 1; + } + else + { + yStart = _scanLineMax; + yStop = _scanLineMin - 1; + dy = -1; + } + + for (int y = yStart; y != yStop; y += dy) + { + if (modp (y, _optimizationMode._ySampling) != 0) + continue; + + // + // Convert one scan line's worth of pixel data back + // from the machine-independent representation, and + // store the result in the frame buffer. + // + + // Set the readPtr to read at the start of uncompressedData + // but with an offet based on calculated array. + // _ifd->offsetInLineBuffer contains offsets based on which + // line we are currently processing. + // Stride will be taken into consideration later. + + + const char* readPtr = _lineBuffer->uncompressedData + + _ifd->offsetInLineBuffer[y - _ifd->minY]; + + size_t pixelsToCopySSE = 0; + size_t pixelsToCopyNormal = 0; + + unsigned short* writePtrLeft = 0; + unsigned short* writePtrRight = 0; + + size_t channels = _ifd->optimizationData.size(); + + if(channels>4) + { + getWritePointerStereo(y, writePtrRight, writePtrLeft, pixelsToCopySSE, pixelsToCopyNormal); + } + else + { + getWritePointer(y, writePtrRight, pixelsToCopySSE, pixelsToCopyNormal); + } + + if (writePtrRight == 0 && pixelsToCopySSE == 0 && pixelsToCopyNormal == 0) + { + continue; + } + + + // + // support reading up to eight channels + // + unsigned short* readPointers[8]; + + for (size_t i = 0; i < channels ; ++i) + { + readPointers[i] = (unsigned short*)readPtr + (_ifd->optimizationData[i].offset * (pixelsToCopySSE * 8 + pixelsToCopyNormal)); + } + + //RGB only + if(channels==3 || channels == 6 ) + { + optimizedWriteToRGB(readPointers[0], readPointers[1], readPointers[2], writePtrRight, pixelsToCopySSE, pixelsToCopyNormal); + + //stereo RGB + if( channels == 6) + { + optimizedWriteToRGB(readPointers[3], readPointers[4], readPointers[5], writePtrLeft, pixelsToCopySSE, pixelsToCopyNormal); + } + //RGBA + }else if(channels==4 || channels==8) + { + + if(_ifd->optimizationData[3].fill) + { + optimizedWriteToRGBAFillA(readPointers[0], readPointers[1], readPointers[2], _ifd->optimizationData[3].fillValue.bits() , writePtrRight, pixelsToCopySSE, pixelsToCopyNormal); + }else{ + optimizedWriteToRGBA(readPointers[0], readPointers[1], readPointers[2], readPointers[3] , writePtrRight, pixelsToCopySSE, pixelsToCopyNormal); + } + + //stereo RGBA + if( channels == 8) + { + if(_ifd->optimizationData[7].fill) + { + optimizedWriteToRGBAFillA(readPointers[4], readPointers[5], readPointers[6], _ifd->optimizationData[7].fillValue.bits() , writePtrLeft, pixelsToCopySSE, pixelsToCopyNormal); + }else{ + optimizedWriteToRGBA(readPointers[4], readPointers[5], readPointers[6], readPointers[7] , writePtrLeft, pixelsToCopySSE, pixelsToCopyNormal); + } + } + } + else { + throw(IEX_NAMESPACE::LogicExc("IIF mode called with incorrect channel pattern")); + } + + // If we are in NO_OPTIMIZATION mode, this class will never + // get instantiated, so no need to check for it and duplicate + // the code. + } } catch (std::exception &e) { - if (!lineBuffer->hasException) - { - lineBuffer->exception = e.what(); - lineBuffer->hasException = true; - } - lineBuffer->number = -1; - lineBuffer->post();\ - throw; + if (!_lineBuffer->hasException) + { + _lineBuffer->exception = e.what(); + _lineBuffer->hasException = true; + } } catch (...) { - // - // Reading from the file caused an exception. - // Signal that the line buffer is free, and - // re-throw the exception. - // - - lineBuffer->exception = "unrecognized exception"; - lineBuffer->hasException = true; - lineBuffer->number = -1; - lineBuffer->post(); - throw; + if (!_lineBuffer->hasException) + { + _lineBuffer->exception = "unrecognized exception"; + _lineBuffer->hasException = true; + } } +} +#endif - scanLineMin = max (lineBuffer->minY, scanLineMin); - scanLineMax = min (lineBuffer->maxY, scanLineMax); - return new LineBufferTask (group, ifd, lineBuffer, - scanLineMin, scanLineMax); -} +Task * +newLineBufferTask (TaskGroup *group, + InputStreamMutex *streamData, + ScanLineInputFile::Data *ifd, + int number, + int scanLineMin, + int scanLineMax, + OptimizationMode optimizationMode) +{ + // + // Wait for a line buffer to become available, fill the line + // buffer with raw data from the file if necessary, and create + // a new LineBufferTask whose execute() method will uncompress + // the contents of the buffer and copy the pixels into the + // frame buffer. + // + + LineBuffer *lineBuffer = ifd->getLineBuffer (number); + + try + { + lineBuffer->wait (); + + if (lineBuffer->number != number) + { + lineBuffer->minY = ifd->minY + number * ifd->linesInBuffer; + lineBuffer->maxY = lineBuffer->minY + ifd->linesInBuffer - 1; + + lineBuffer->number = number; + lineBuffer->uncompressedData = 0; + + readPixelData (streamData, ifd, lineBuffer->minY, + lineBuffer->buffer, + lineBuffer->dataSize); + } + } + catch (std::exception &e) + { + if (!lineBuffer->hasException) + { + lineBuffer->exception = e.what(); + lineBuffer->hasException = true; + } + lineBuffer->number = -1; + lineBuffer->post(); + throw; + } + catch (...) + { + // + // Reading from the file caused an exception. + // Signal that the line buffer is free, and + // re-throw the exception. + // + + lineBuffer->exception = "unrecognized exception"; + lineBuffer->hasException = true; + lineBuffer->number = -1; + lineBuffer->post(); + throw; + } + + scanLineMin = max (lineBuffer->minY, scanLineMin); + scanLineMax = min (lineBuffer->maxY, scanLineMax); + + + Task* retTask = 0; + +#ifdef IMF_HAVE_SSE2 + if (optimizationMode._optimizable) + { + + retTask = new LineBufferTaskIIF (group, ifd, lineBuffer, + scanLineMin, scanLineMax, + optimizationMode); + + } + else +#endif + { + retTask = new LineBufferTask (group, ifd, lineBuffer, + scanLineMin, scanLineMax, + optimizationMode); + } + + return retTask; + + } + + + } // namespace -ScanLineInputFile::ScanLineInputFile - (const Header &header, - IStream *is, - int numThreads) -: - _data (new Data (is, numThreads)) +void ScanLineInputFile::initialize(const Header& header) { try { - _data->header = header; + _data->header = header; - _data->lineOrder = _data->header.lineOrder(); + _data->lineOrder = _data->header.lineOrder(); - const Box2i &dataWindow = _data->header.dataWindow(); + const Box2i &dataWindow = _data->header.dataWindow(); - _data->minX = dataWindow.min.x; - _data->maxX = dataWindow.max.x; - _data->minY = dataWindow.min.y; - _data->maxY = dataWindow.max.y; + _data->minX = dataWindow.min.x; + _data->maxX = dataWindow.max.x; + _data->minY = dataWindow.min.y; + _data->maxY = dataWindow.max.y; - size_t maxBytesPerLine = bytesPerLineTable (_data->header, + size_t maxBytesPerLine = bytesPerLineTable (_data->header, _data->bytesPerLine); for (size_t i = 0; i < _data->lineBuffers.size(); i++) @@ -691,43 +1123,106 @@ ScanLineInputFile::ScanLineInputFile } _data->linesInBuffer = - numLinesInBuffer (_data->lineBuffers[0]->compressor); + numLinesInBuffer (_data->lineBuffers[0]->compressor); _data->lineBufferSize = maxBytesPerLine * _data->linesInBuffer; - if (!_data->is->isMemoryMapped()) + if (!_streamData->is->isMemoryMapped()) + { for (size_t i = 0; i < _data->lineBuffers.size(); i++) - _data->lineBuffers[i]->buffer = new char[_data->lineBufferSize]; - - _data->nextLineBufferMinY = _data->minY - 1; - - offsetInLineBufferTable (_data->bytesPerLine, - _data->linesInBuffer, - _data->offsetInLineBuffer); + { + _data->lineBuffers[i]->buffer = (char *) EXRAllocAligned(_data->lineBufferSize*sizeof(char),16); + } + } + _data->nextLineBufferMinY = _data->minY - 1; - int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y + - _data->linesInBuffer) / _data->linesInBuffer; + offsetInLineBufferTable (_data->bytesPerLine, + _data->linesInBuffer, + _data->offsetInLineBuffer); - _data->lineOffsets.resize (lineOffsetSize); + int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y + + _data->linesInBuffer) / _data->linesInBuffer; - readLineOffsets (*_data->is, - _data->lineOrder, - _data->lineOffsets, - _data->fileIsComplete); + _data->lineOffsets.resize (lineOffsetSize); } catch (...) { - delete _data; - throw; + delete _data; + _data=NULL; + throw; } } +ScanLineInputFile::ScanLineInputFile(InputPartData* part) +{ + if (part->header.type() != SCANLINEIMAGE) + throw IEX_NAMESPACE::ArgExc("Can't build a ScanLineInputFile from a type-mismatched part."); + + _data = new Data(part->numThreads); + _streamData = part->mutex; + _data->memoryMapped = _streamData->is->isMemoryMapped(); + + _data->version = part->version; + + initialize(part->header); + + _data->lineOffsets = part->chunkOffsets; + + _data->partNumber = part->partNumber; + // + // (TODO) change this code later. + // The completeness of the file should be detected in MultiPartInputFile. + // + _data->fileIsComplete = true; +} + + +ScanLineInputFile::ScanLineInputFile + (const Header &header, + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, + int numThreads) +: + _data (new Data (numThreads)), + _streamData (new InputStreamMutex()) +{ + _streamData->is = is; + _data->memoryMapped = is->isMemoryMapped(); + + initialize(header); + + // + // (TODO) this is nasty - we need a better way of working out what type of file has been used. + // in any case I believe this constructor only gets used with single part files + // and 'version' currently only tracks multipart state, so setting to 0 (not multipart) works for us + // + + _data->version=0; + readLineOffsets (*_streamData->is, + _data->lineOrder, + _data->lineOffsets, + _data->fileIsComplete); +} + + ScanLineInputFile::~ScanLineInputFile () { - if (!_data->is->isMemoryMapped()) + if (!_data->memoryMapped) + { for (size_t i = 0; i < _data->lineBuffers.size(); i++) - delete [] _data->lineBuffers[i]->buffer; + { + EXRFreeAligned(_data->lineBuffers[i]->buffer); + } + } + + + // + // ScanLineInputFile should never delete the stream, + // because it does not own the stream. + // We just delete the Mutex here. + // + if (_data->partNumber == -1) + delete _streamData; delete _data; } @@ -736,7 +1231,7 @@ ScanLineInputFile::~ScanLineInputFile () const char * ScanLineInputFile::fileName () const { - return _data->is->fileName(); + return _streamData->is->fileName(); } @@ -754,109 +1249,285 @@ ScanLineInputFile::version () const } -void -ScanLineInputFile::setFrameBuffer (const FrameBuffer &frameBuffer) +namespace { - Lock lock (*_data); - + + +// returns the optimization state for the given arrangement of frame bufers +// this assumes: +// both the file and framebuffer are half float data +// both the file and framebuffer have xSampling and ySampling=1 +// entries in optData are sorted into their interleave order (i.e. by base address) +// These tests are done by SetFrameBuffer as it is building optData +// +OptimizationMode +detectOptimizationMode (const vector& optData) +{ + OptimizationMode w; + + // need to be compiled with SSE optimisations: if not, just returns false +#ifdef IMF_HAVE_SSE2 + + + // only handle reading 3,4,6 or 8 channels + switch(optData.size()) + { + case 3 : break; + case 4 : break; + case 6 : break; + case 8 : break; + default : + return w; + } + // - // Check if the new frame buffer descriptor is - // compatible with the image file header. + // the point at which data switches between the primary and secondary bank // + size_t bankSize = optData.size()>4 ? optData.size()/2 : optData.size(); + + for(size_t i=0;iheader.channels(); + w._ySampling=optData[0].ySampling; + w._optimizable=true; + +#endif + + return w; +} + + +} // Anonymous namespace + +void +ScanLineInputFile::setFrameBuffer (const FrameBuffer &frameBuffer) +{ + Lock lock (*_streamData); + + + const ChannelList &channels = _data->header.channels(); for (FrameBuffer::ConstIterator j = frameBuffer.begin(); - j != frameBuffer.end(); - ++j) + j != frameBuffer.end(); + ++j) { - ChannelList::ConstIterator i = channels.find (j.name()); - - if (i == channels.end()) - continue; - - if (i.channel().xSampling != j.slice().xSampling || - i.channel().ySampling != j.slice().ySampling) - THROW (Iex::ArgExc, "X and/or y subsampling factors " - "of \"" << i.name() << "\" channel " - "of input file \"" << fileName() << "\" are " - "not compatible with the frame buffer's " - "subsampling factors."); + ChannelList::ConstIterator i = channels.find (j.name()); + + if (i == channels.end()) + continue; + + if (i.channel().xSampling != j.slice().xSampling || + i.channel().ySampling != j.slice().ySampling) + THROW (IEX_NAMESPACE::ArgExc, "X and/or y subsampling factors " + "of \"" << i.name() << "\" channel " + "of input file \"" << fileName() << "\" are " + "not compatible with the frame buffer's " + "subsampling factors."); } + // optimization is possible if this is a little endian system + // and both inputs and outputs are half floats + // + bool optimizationPossible = true; + + if (!GLOBAL_SYSTEM_LITTLE_ENDIAN) + { + optimizationPossible =false; + } + + vector optData; + + // // Initialize the slice table for readPixels(). // vector slices; ChannelList::ConstIterator i = channels.begin(); - + + // current offset of channel: pixel data starts at offset*width into the + // decompressed scanline buffer + size_t offset = 0; + for (FrameBuffer::ConstIterator j = frameBuffer.begin(); - j != frameBuffer.end(); - ++j) - { - while (i != channels.end() && strcmp (i.name(), j.name()) < 0) - { - // - // Channel i is present in the file but not - // in the frame buffer; data for channel i - // will be skipped during readPixels(). - // - - slices.push_back (InSliceInfo (i.channel().type, - i.channel().type, - 0, // base - 0, // xStride - 0, // yStride - i.channel().xSampling, - i.channel().ySampling, - false, // fill - true, // skip - 0.0)); // fillValue - ++i; - } - - bool fill = false; - - if (i == channels.end() || strcmp (i.name(), j.name()) > 0) + j != frameBuffer.end(); + ++j) { - // - // Channel i is present in the frame buffer, but not in the file. - // In the frame buffer, slice j will be filled with a default value. - // - - fill = true; - } - - slices.push_back (InSliceInfo (j.slice().type, - fill? j.slice().type: - i.channel().type, - j.slice().base, - j.slice().xStride, - j.slice().yStride, - j.slice().xSampling, - j.slice().ySampling, - fill, - false, // skip - j.slice().fillValue)); - - if (i != channels.end() && !fill) - ++i; + while (i != channels.end() && strcmp (i.name(), j.name()) < 0) + { + // + // Channel i is present in the file but not + // in the frame buffer; data for channel i + // will be skipped during readPixels(). + // + + slices.push_back (InSliceInfo (i.channel().type, + i.channel().type, + 0, // base + 0, // xStride + 0, // yStride + i.channel().xSampling, + i.channel().ySampling, + false, // fill + true, // skip + 0.0)); // fillValue + + switch(i.channel().type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF : + offset++; + break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT : + offset+=2; + break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT : + offset+=2; + break; + } + ++i; + } + + bool fill = false; + + if (i == channels.end() || strcmp (i.name(), j.name()) > 0) + { + // + // Channel i is present in the frame buffer, but not in the file. + // In the frame buffer, slice j will be filled with a default value. + // + + fill = true; + } + + slices.push_back (InSliceInfo (j.slice().type, + fill? j.slice().type: + i.channel().type, + j.slice().base, + j.slice().xStride, + j.slice().yStride, + j.slice().xSampling, + j.slice().ySampling, + fill, + false, // skip + j.slice().fillValue)); + + if(!fill && i.channel().type!=OPENEXR_IMF_INTERNAL_NAMESPACE::HALF) + { + optimizationPossible = false; + } + + if(j.slice().type != OPENEXR_IMF_INTERNAL_NAMESPACE::HALF) + { + optimizationPossible = false; + } + if(j.slice().xSampling!=1 || j.slice().ySampling!=1) + { + optimizationPossible = false; + } + + + if(optimizationPossible) + { + sliceOptimizationData dat; + dat.base = j.slice().base; + dat.fill = fill; + dat.fillValue = j.slice().fillValue; + dat.offset = offset; + dat.xStride = j.slice().xStride; + dat.yStride = j.slice().yStride; + dat.xSampling = j.slice().xSampling; + dat.ySampling = j.slice().ySampling; + optData.push_back(dat); + } + + if(!fill) + { + switch(i.channel().type) + { + case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF : + offset++; + break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT : + offset+=2; + break; + case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT : + offset+=2; + break; + } + } + + + + if (i != channels.end() && !fill) + ++i; } + + if(optimizationPossible) + { + // + // check optimisibility + // based on channel ordering and fill channel positions + // + sort(optData.begin(),optData.end()); + _data->optimizationMode = detectOptimizationMode(optData); + } + + if(!optimizationPossible || _data->optimizationMode._optimizable==false) + { + optData = vector(); + _data->optimizationMode._optimizable=false; + } + // // Store the new frame buffer. // _data->frameBuffer = frameBuffer; _data->slices = slices; + _data->optimizationData = optData; } const FrameBuffer & ScanLineInputFile::frameBuffer () const { - Lock lock (*_data); + Lock lock (*_streamData); return _data->frameBuffer; } @@ -867,24 +1538,33 @@ ScanLineInputFile::isComplete () const return _data->fileIsComplete; } +bool ScanLineInputFile::isOptimizationEnabled() const +{ + if (_data->slices.size() == 0) + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data destination."); + + return _data->optimizationMode._optimizable; +} -void + +void ScanLineInputFile::readPixels (int scanLine1, int scanLine2) { try { - Lock lock (*_data); + Lock lock (*_streamData); - if (_data->slices.size() == 0) - throw Iex::ArgExc ("No frame buffer specified " - "as pixel data destination."); + if (_data->slices.size() == 0) + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data destination."); - int scanLineMin = min (scanLine1, scanLine2); - int scanLineMax = max (scanLine1, scanLine2); + int scanLineMin = min (scanLine1, scanLine2); + int scanLineMax = max (scanLine1, scanLine2); - if (scanLineMin < _data->minY || scanLineMax > _data->maxY) - throw Iex::ArgExc ("Tried to read scan line outside " - "the image file's data window."); + if (scanLineMin < _data->minY || scanLineMax > _data->maxY) + throw IEX_NAMESPACE::ArgExc ("Tried to read scan line outside " + "the image file's data window."); // // We impose a numbering scheme on the lineBuffers where the first @@ -912,76 +1592,78 @@ ScanLineInputFile::readPixels (int scanLine1, int scanLine2) // // Create a task group for all line buffer tasks. When the - // task group goes out of scope, the destructor waits until - // all tasks are complete. + // task group goes out of scope, the destructor waits until + // all tasks are complete. // - + { TaskGroup taskGroup; - + // // Add the line buffer tasks. // // The tasks will execute in the order that they are created // because we lock the line buffers during construction and the // constructors are called by the main thread. Hence, in order - // for a successive task to execute the previous task which - // used that line buffer must have completed already. + // for a successive task to execute the previous task which + // used that line buffer must have completed already. // - + for (int l = start; l != stop; l += dl) { ThreadPool::addGlobalTask (newLineBufferTask (&taskGroup, + _streamData, _data, l, scanLineMin, - scanLineMax)); + scanLineMax, + _data->optimizationMode)); } - - // + + // // finish all tasks - // + // } - - // - // Exeption handling: - // - // LineBufferTask::execute() may have encountered exceptions, but - // those exceptions occurred in another thread, not in the thread - // that is executing this call to ScanLineInputFile::readPixels(). - // LineBufferTask::execute() has caught all exceptions and stored - // the exceptions' what() strings in the line buffers. - // Now we check if any line buffer contains a stored exception; if - // this is the case then we re-throw the exception in this thread. - // (It is possible that multiple line buffers contain stored - // exceptions. We re-throw the first exception we find and - // ignore all others.) - // - - const string *exception = 0; - - for (int i = 0; i < _data->lineBuffers.size(); ++i) - { + + // + // Exeption handling: + // + // LineBufferTask::execute() may have encountered exceptions, but + // those exceptions occurred in another thread, not in the thread + // that is executing this call to ScanLineInputFile::readPixels(). + // LineBufferTask::execute() has caught all exceptions and stored + // the exceptions' what() strings in the line buffers. + // Now we check if any line buffer contains a stored exception; if + // this is the case then we re-throw the exception in this thread. + // (It is possible that multiple line buffers contain stored + // exceptions. We re-throw the first exception we find and + // ignore all others.) + // + + const string *exception = 0; + + for (size_t i = 0; i < _data->lineBuffers.size(); ++i) + { LineBuffer *lineBuffer = _data->lineBuffers[i]; - if (lineBuffer->hasException && !exception) - exception = &lineBuffer->exception; + if (lineBuffer->hasException && !exception) + exception = &lineBuffer->exception; - lineBuffer->hasException = false; - } + lineBuffer->hasException = false; + } - if (exception) - throw Iex::IoExc (*exception); + if (exception) + throw IEX_NAMESPACE::IoExc (*exception); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error reading pixel data from image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error reading pixel data from image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } -void +void ScanLineInputFile::readPixels (int scanLine) { readPixels (scanLine, scanLine); @@ -990,33 +1672,67 @@ ScanLineInputFile::readPixels (int scanLine) void ScanLineInputFile::rawPixelData (int firstScanLine, - const char *&pixelData, - int &pixelDataSize) + const char *&pixelData, + int &pixelDataSize) { try { - Lock lock (*_data); + Lock lock (*_streamData); - if (firstScanLine < _data->minY || firstScanLine > _data->maxY) - { - throw Iex::ArgExc ("Tried to read scan line outside " - "the image file's data window."); - } + if (firstScanLine < _data->minY || firstScanLine > _data->maxY) + { + throw IEX_NAMESPACE::ArgExc ("Tried to read scan line outside " + "the image file's data window."); + } int minY = lineBufferMinY - (firstScanLine, _data->minY, _data->linesInBuffer); + (firstScanLine, _data->minY, _data->linesInBuffer); - readPixelData - (_data, minY, _data->lineBuffers[0]->buffer, pixelDataSize); + readPixelData + (_streamData, _data, minY, _data->lineBuffers[0]->buffer, pixelDataSize); - pixelData = _data->lineBuffers[0]->buffer; + pixelData = _data->lineBuffers[0]->buffer; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + REPLACE_EXC (e, "Error reading pixel data from image " + "file \"" << fileName() << "\". " << e.what()); + throw; } - catch (Iex::BaseExc &e) +} + + +void ScanLineInputFile::rawPixelDataToBuffer(int scanLine, + char *pixelData, + int &pixelDataSize) const +{ + if (_data->memoryMapped) { + throw IEX_NAMESPACE::ArgExc ("Reading raw pixel data to a buffer " + "is not supported for memory mapped " + "streams." ); + } + + try + { + Lock lock (*_streamData); + + if (scanLine < _data->minY || scanLine > _data->maxY) { + throw IEX_NAMESPACE::ArgExc ("Tried to read scan line outside " + "the image file's data window."); + } + + readPixelData + (_streamData, _data, scanLine, pixelData, pixelDataSize); + + } + catch (IEX_NAMESPACE::BaseExc &e) + { REPLACE_EXC (e, "Error reading pixel data from image " - "file \"" << fileName() << "\". " << e); + "file \"" << fileName() << "\". " << e.what()); throw; - } + } } -} // namespace Imf + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.h b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.h index 70f2f3943a..3165a716d3 100644 --- a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.h +++ b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,14 +42,19 @@ // //----------------------------------------------------------------------------- -#include -#include -#include +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" +#include "ImfThreading.h" +#include "ImfInputStreamMutex.h" +#include "ImfInputPartData.h" +#include "ImfGenericInputFile.h" +#include "ImfExport.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -class ScanLineInputFile +class ScanLineInputFile : public GenericInputFile { public: @@ -57,7 +62,8 @@ class ScanLineInputFile // Constructor //------------ - ScanLineInputFile (const Header &header, IStream *is, + IMF_EXPORT + ScanLineInputFile (const Header &header, OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, int numThreads = globalThreadCount()); @@ -66,6 +72,7 @@ class ScanLineInputFile // structures, but does not close the file. //----------------------------------------- + IMF_EXPORT virtual ~ScanLineInputFile (); @@ -73,6 +80,7 @@ class ScanLineInputFile // Access to the file name //------------------------ + IMF_EXPORT const char * fileName () const; @@ -80,6 +88,7 @@ class ScanLineInputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; @@ -87,6 +96,7 @@ class ScanLineInputFile // Access to the file format version //---------------------------------- + IMF_EXPORT int version () const; @@ -101,6 +111,7 @@ class ScanLineInputFile // to readPixels(). //----------------------------------------------------------- + IMF_EXPORT void setFrameBuffer (const FrameBuffer &frameBuffer); @@ -108,6 +119,7 @@ class ScanLineInputFile // Access to the current frame buffer //----------------------------------- + IMF_EXPORT const FrameBuffer & frameBuffer () const; @@ -120,8 +132,30 @@ class ScanLineInputFile // writing may have been aborted prematurely.) //--------------------------------------------------------------- + IMF_EXPORT bool isComplete () const; + + + //--------------------------------------------------------------- + // Check if SSE optimisation is enabled + // + // Call after setFrameBuffer() to query whether optimised file decoding + // is available - decode times will be faster if returns true + // + // Optimisation depends on the framebuffer channels and channel types + // as well as the file/part channels and channel types, as well as + // whether SSE2 instruction support was detected at compile time + // + // Calling before setFrameBuffer will throw an exception + // + //--------------------------------------------------------------- + + IMF_EXPORT + bool isOptimizationEnabled () const; + + + //--------------------------------------------------------------- // Read pixel data: @@ -145,7 +179,9 @@ class ScanLineInputFile // //--------------------------------------------------------------- + IMF_EXPORT void readPixels (int scanLine1, int scanLine2); + IMF_EXPORT void readPixels (int scanLine); @@ -155,18 +191,55 @@ class ScanLineInputFile // used to implement OutputFile::copyPixels()). //---------------------------------------------- + IMF_EXPORT void rawPixelData (int firstScanLine, - const char *&pixelData, - int &pixelDataSize); + const char *&pixelData, + int &pixelDataSize); + + //---------------------------------------------- + // Read a scanline's worth of raw pixel data + // from the file, without uncompressing it, and + // store in an external buffer, pixelData. + // pixelData should be pre-allocated with space + // for pixelDataSize chars. + // + // This function can be used to separate the + // reading of a raw scan line from the + // decompression of that scan line, for + // example to allow multiple scan lines to be + // decompressed in parallel by an application's + // own threads, where it is not convenient to + // use the threading within the library. + //---------------------------------------------- + + IMF_EXPORT + void rawPixelDataToBuffer(int scanLine, + char *pixelData, + int &pixelDataSize) const; + + struct Data; private: Data * _data; + + InputStreamMutex* _streamData; + + ScanLineInputFile (InputPartData* part); + + void initialize(const Header& header); + + friend class MultiPartInputFile; + friend class InputFile; }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfSimd.h b/3rdparty/openexr/IlmImf/ImfSimd.h new file mode 100644 index 0000000000..3489bd0c95 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfSimd.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Autodesk, Inc. +// +// All rights reserved. +// +// Implementation of IIF-specific file format and speed optimizations +// provided by Innobec Technologies inc on behalf of Autodesk. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMF_SIMD_H +#define INCLUDED_IMF_SIMD_H + +// +// Compile time SSE detection: +// IMF_HAVE_SSE2 - Defined if it's safe to compile SSE2 optimizations +// IMF_HAVE_SSE4_1 - Defined if it's safe to compile SSE4.1 optimizations +// + + +// GCC and Visual Studio SSE2 compiler flags +#if defined __SSE2__ || (_MSC_VER >= 1300 && !_M_CEE_PURE) + #define IMF_HAVE_SSE2 1 +#endif + +#if defined __SSE4_1__ + #define IMF_HAVE_SSE4_1 1 +#endif + +extern "C" +{ +#ifdef IMF_HAVE_SSE2 + #include + #include +#endif + +#ifdef IMF_HAVE_SSE4_1 + #include +#endif +} + +#endif diff --git a/3rdparty/openexr/IlmImf/ImfStandardAttributes.cpp b/3rdparty/openexr/IlmImf/ImfStandardAttributes.cpp index ea57020334..df952c2574 100644 --- a/3rdparty/openexr/IlmImf/ImfStandardAttributes.cpp +++ b/3rdparty/openexr/IlmImf/ImfStandardAttributes.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2003, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,59 +45,63 @@ #define IMF_STRING(name) #name #define IMF_STD_ATTRIBUTE_IMP(name,suffix,type) \ - \ + \ void \ add##suffix (Header &header, const type &value) \ { \ - header.insert (IMF_STRING (name), TypedAttribute (value)); \ + header.insert (IMF_STRING (name), TypedAttribute (value)); \ } \ - \ + \ bool \ has##suffix (const Header &header) \ { \ - return header.findTypedAttribute > \ - (IMF_STRING (name)) != 0; \ + return header.findTypedAttribute > \ + (IMF_STRING (name)) != 0; \ } \ - \ + \ const TypedAttribute & \ name##Attribute (const Header &header) \ { \ - return header.typedAttribute > \ - (IMF_STRING (name)); \ + return header.typedAttribute > \ + (IMF_STRING (name)); \ } \ - \ + \ TypedAttribute & \ name##Attribute (Header &header) \ { \ - return header.typedAttribute > \ - (IMF_STRING (name)); \ + return header.typedAttribute > \ + (IMF_STRING (name)); \ } \ - \ + \ const type & \ name (const Header &header) \ { \ - return name##Attribute(header).value(); \ + return name##Attribute(header).value(); \ } \ - \ + \ type & \ name (Header &header) \ { \ - return name##Attribute(header).value(); \ + return name##Attribute(header).value(); \ } +#include "ImfNamespace.h" -namespace Imf { +using namespace IMATH_NAMESPACE; +using namespace std; +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + IMF_STD_ATTRIBUTE_IMP (chromaticities, Chromaticities, Chromaticities) IMF_STD_ATTRIBUTE_IMP (whiteLuminance, WhiteLuminance, float) -IMF_STD_ATTRIBUTE_IMP (adoptedNeutral, AdoptedNeutral, Imath::V2f) -IMF_STD_ATTRIBUTE_IMP (renderingTransform, RenderingTransform, std::string) -IMF_STD_ATTRIBUTE_IMP (lookModTransform, LookModTransform, std::string) +IMF_STD_ATTRIBUTE_IMP (adoptedNeutral, AdoptedNeutral, V2f) +IMF_STD_ATTRIBUTE_IMP (renderingTransform, RenderingTransform, string) +IMF_STD_ATTRIBUTE_IMP (lookModTransform, LookModTransform, string) IMF_STD_ATTRIBUTE_IMP (xDensity, XDensity, float) -IMF_STD_ATTRIBUTE_IMP (owner, Owner, std::string) -IMF_STD_ATTRIBUTE_IMP (comments, Comments, std::string) -IMF_STD_ATTRIBUTE_IMP (capDate, CapDate, std::string) +IMF_STD_ATTRIBUTE_IMP (owner, Owner, string) +IMF_STD_ATTRIBUTE_IMP (comments, Comments, string) +IMF_STD_ATTRIBUTE_IMP (capDate, CapDate, string) IMF_STD_ATTRIBUTE_IMP (utcOffset, UtcOffset, float) IMF_STD_ATTRIBUTE_IMP (longitude, Longitude, float) IMF_STD_ATTRIBUTE_IMP (latitude, Latitude, float) @@ -109,10 +113,13 @@ IMF_STD_ATTRIBUTE_IMP (isoSpeed, IsoSpeed, float) IMF_STD_ATTRIBUTE_IMP (envmap, Envmap, Envmap) IMF_STD_ATTRIBUTE_IMP (keyCode, KeyCode, KeyCode) IMF_STD_ATTRIBUTE_IMP (timeCode, TimeCode, TimeCode) -IMF_STD_ATTRIBUTE_IMP (wrapmodes, Wrapmodes, std::string) +IMF_STD_ATTRIBUTE_IMP (wrapmodes, Wrapmodes, string) IMF_STD_ATTRIBUTE_IMP (framesPerSecond, FramesPerSecond, Rational) IMF_STD_ATTRIBUTE_IMP (multiView, MultiView, StringVector) -IMF_STD_ATTRIBUTE_IMP (worldToCamera, WorldToCamera, Imath::M44f) -IMF_STD_ATTRIBUTE_IMP (worldToNDC, WorldToNDC, Imath::M44f) +IMF_STD_ATTRIBUTE_IMP (worldToCamera, WorldToCamera, M44f) +IMF_STD_ATTRIBUTE_IMP (worldToNDC, WorldToNDC, M44f) +IMF_STD_ATTRIBUTE_IMP (deepImageState, DeepImageState, DeepImageState) +IMF_STD_ATTRIBUTE_IMP (originalDataWindow, OriginalDataWindow, Box2i) +IMF_STD_ATTRIBUTE_IMP (dwaCompressionLevel, DwaCompressionLevel, float) -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfStandardAttributes.h b/3rdparty/openexr/IlmImf/ImfStandardAttributes.h index 72735974ee..4280ac4c1c 100644 --- a/3rdparty/openexr/IlmImf/ImfStandardAttributes.h +++ b/3rdparty/openexr/IlmImf/ImfStandardAttributes.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -54,29 +54,35 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IMF_STD_ATTRIBUTE_DEF(name,suffix,type) \ - \ - void add##suffix (Header &header, const type &v); \ - bool has##suffix (const Header &header); \ - const TypedAttribute & name##Attribute (const Header &header); \ - TypedAttribute & name##Attribute (Header &header); \ - const type & name (const Header &header); \ - type & name (Header &header); - - -namespace Imf { +#include "ImfHeader.h" +#include "ImfBoxAttribute.h" +#include "ImfChromaticitiesAttribute.h" +#include "ImfEnvmapAttribute.h" +#include "ImfDeepImageStateAttribute.h" +#include "ImfFloatAttribute.h" +#include "ImfKeyCodeAttribute.h" +#include "ImfMatrixAttribute.h" +#include "ImfRationalAttribute.h" +#include "ImfStringAttribute.h" +#include "ImfStringVectorAttribute.h" +#include "ImfTimeCodeAttribute.h" +#include "ImfVecAttribute.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +#define IMF_STD_ATTRIBUTE_DEF(name,suffix,object) \ + \ + OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER \ + IMF_EXPORT void add##suffix (Header &header, const object &v); \ + IMF_EXPORT bool has##suffix (const Header &header); \ + IMF_EXPORT const TypedAttribute & \ + name##Attribute (const Header &header); \ + IMF_EXPORT TypedAttribute & \ + name##Attribute (Header &header); \ + IMF_EXPORT const object & \ + name (const Header &header); \ + IMF_EXPORT object & name (Header &header); \ + OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT \ // // chromaticities -- for RGB images, specifies the CIE (x,y) @@ -94,7 +100,7 @@ IMF_STD_ATTRIBUTE_DEF (chromaticities, Chromaticities, Chromaticities) // known, then it is possible to convert the image's pixels from RGB // to CIE XYZ tristimulus values (see function RGBtoXYZ() in header // file ImfChromaticities.h). -// +// // IMF_STD_ATTRIBUTE_DEF (whiteLuminance, WhiteLuminance, float) @@ -107,14 +113,14 @@ IMF_STD_ATTRIBUTE_DEF (whiteLuminance, WhiteLuminance, float) // be mapped to neutral values on the display. // -IMF_STD_ATTRIBUTE_DEF (adoptedNeutral, AdoptedNeutral, Imath::V2f) +IMF_STD_ATTRIBUTE_DEF (adoptedNeutral, AdoptedNeutral, IMATH_NAMESPACE::V2f) // // renderingTransform, lookModTransform -- specify the names of the // CTL functions that implements the intended color rendering and look // modification transforms for this image. -// +// IMF_STD_ATTRIBUTE_DEF (renderingTransform, RenderingTransform, std::string) IMF_STD_ATTRIBUTE_DEF (lookModTransform, LookModTransform, std::string) @@ -133,7 +139,7 @@ IMF_STD_ATTRIBUTE_DEF (xDensity, XDensity, float) // IMF_STD_ATTRIBUTE_DEF (owner, Owner, std::string) - + // // comments -- additional image information in human-readable @@ -302,42 +308,75 @@ IMF_STD_ATTRIBUTE_DEF (framesPerSecond, FramesPerSecond, Rational) IMF_STD_ATTRIBUTE_DEF (multiView , MultiView, StringVector) -// +// // worldToCamera -- for images generated by 3D computer graphics rendering, // a matrix that transforms 3D points from the world to the camera coordinate // space of the renderer. -// +// // The camera coordinate space is left-handed. Its origin indicates the // location of the camera. The positive x and y axes correspond to the // "right" and "up" directions in the rendered image. The positive z // axis indicates the camera's viewing direction. (Objects in front of // the camera have positive z coordinates.) -// +// // Camera coordinate space in OpenEXR is the same as in Pixar's Renderman. -// +// -IMF_STD_ATTRIBUTE_DEF (worldToCamera, WorldToCamera, Imath::M44f) +IMF_STD_ATTRIBUTE_DEF (worldToCamera, WorldToCamera, IMATH_NAMESPACE::M44f) -// +// // worldToNDC -- for images generated by 3D computer graphics rendering, a // matrix that transforms 3D points from the world to the Normalized Device // Coordinate (NDC) space of the renderer. -// +// // NDC is a 2D coordinate space that corresponds to the image plane, with // positive x and pointing to the right and y positive pointing down. The // coordinates (0, 0) and (1, 1) correspond to the upper left and lower right // corners of the OpenEXR display window. -// +// // To transform a 3D point in word space into a 2D point in NDC space, // multiply the 3D point by the worldToNDC matrix and discard the z // coordinate. -// +// // NDC space in OpenEXR is the same as in Pixar's Renderman. +// + +IMF_STD_ATTRIBUTE_DEF (worldToNDC, WorldToNDC, IMATH_NAMESPACE::M44f) + + +// +// deepImageState -- specifies whether the pixels in a deep image are +// sorted and non-overlapping. +// +// Note: this attribute can be set by application code that writes a file +// in order to tell applications that read the file whether the pixel data +// must be cleaned up prior to image processing operations such as flattening. +// The IlmImf library does not verify that the attribute is consistent with +// the actual state of the pixels. Application software may assume that the +// attribute is valid, as long as the software will not crash or lock up if +// any pixels are inconsistent with the deepImageState attribute. +// + +IMF_STD_ATTRIBUTE_DEF (deepImageState, DeepImageState, DeepImageState) + + +// +// originalDataWindow -- if application software crops an image, then it +// should save the data window of the original, un-cropped image in the +// originalDataWindow attribute. +// + +IMF_STD_ATTRIBUTE_DEF + (originalDataWindow, OriginalDataWindow, IMATH_NAMESPACE::Box2i) + + +// +// dwaCompressionLevel -- sets the quality level for images compressed +// with the DWAA or DWAB method. // -IMF_STD_ATTRIBUTE_DEF (worldToNDC, WorldToNDC, Imath::M44f) +IMF_STD_ATTRIBUTE_DEF (dwaCompressionLevel, DwaCompressionLevel, float) -} // namespace Imf #endif diff --git a/3rdparty/openexr/IlmImf/ImfStdIO.cpp b/3rdparty/openexr/IlmImf/ImfStdIO.cpp index 973d60e112..91252dffd6 100644 --- a/3rdparty/openexr/IlmImf/ImfStdIO.cpp +++ b/3rdparty/openexr/IlmImf/ImfStdIO.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,12 +43,34 @@ #include #include "Iex.h" #include +#ifdef _MSC_VER +# define VC_EXTRALEAN +# include +# include +#endif using namespace std; +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { namespace { +#ifdef _MSC_VER +std::wstring WidenFilename (const char *filename) +{ + std::wstring ret; + int fnlen = static_cast( strlen(filename) ); + int len = MultiByteToWideChar(CP_UTF8, 0, filename, fnlen, NULL, 0 ); + if (len > 0) + { + ret.resize(len); + MultiByteToWideChar(CP_UTF8, 0, filename, fnlen, &ret[0], len); + } + return ret; +} +#endif + void clearError () { @@ -61,15 +83,15 @@ checkError (istream &is, streamsize expected = 0) { if (!is) { - if (errno) - Iex::throwErrnoExc(); - - if (is.gcount() < expected) - { - THROW (Iex::InputExc, "Early end of file: read " << is.gcount() - << " out of " << expected << " requested bytes."); - } - return false; + if (errno) + IEX_NAMESPACE::throwErrnoExc(); + + if (is.gcount() < expected) + { + THROW (IEX_NAMESPACE::InputExc, "Early end of file: read " << is.gcount() + << " out of " << expected << " requested bytes."); + } + return false; } return true; @@ -81,10 +103,10 @@ checkError (ostream &os) { if (!os) { - if (errno) - Iex::throwErrnoExc(); + if (errno) + IEX_NAMESPACE::throwErrnoExc(); - throw Iex::ErrnoExc ("File output failed."); + throw IEX_NAMESPACE::ErrnoExc ("File output failed."); } } @@ -92,20 +114,26 @@ checkError (ostream &os) StdIFStream::StdIFStream (const char fileName[]): - IStream (fileName), - _is (new ifstream (fileName, ios_base::binary)), + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream (fileName), + _is (new ifstream ( +#ifdef _MSC_VER + WidenFilename(fileName).c_str(), +#else + fileName, +#endif + ios_base::binary)), _deleteStream (true) { if (!*_is) { - delete _is; - Iex::throwErrnoExc(); + delete _is; + IEX_NAMESPACE::throwErrnoExc(); } } - + StdIFStream::StdIFStream (ifstream &is, const char fileName[]): - IStream (fileName), + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream (fileName), _is (&is), _deleteStream (false) { @@ -116,7 +144,7 @@ StdIFStream::StdIFStream (ifstream &is, const char fileName[]): StdIFStream::~StdIFStream () { if (_deleteStream) - delete _is; + delete _is; } @@ -124,7 +152,7 @@ bool StdIFStream::read (char c[/*n*/], int n) { if (!*_is) - throw Iex::InputExc ("Unexpected end of file."); + throw IEX_NAMESPACE::InputExc ("Unexpected end of file."); clearError(); _is->read (c, n); @@ -155,20 +183,26 @@ StdIFStream::clear () StdOFStream::StdOFStream (const char fileName[]): - OStream (fileName), - _os (new ofstream (fileName, ios_base::binary)), + OPENEXR_IMF_INTERNAL_NAMESPACE::OStream (fileName), + _os (new ofstream ( +#ifdef _MSC_VER + WidenFilename(fileName).c_str(), +#else + fileName, +#endif + ios_base::binary)), _deleteStream (true) { if (!*_os) { - delete _os; - Iex::throwErrnoExc(); + delete _os; + IEX_NAMESPACE::throwErrnoExc(); } } StdOFStream::StdOFStream (ofstream &os, const char fileName[]): - OStream (fileName), + OPENEXR_IMF_INTERNAL_NAMESPACE::OStream (fileName), _os (&os), _deleteStream (false) { @@ -179,7 +213,7 @@ StdOFStream::StdOFStream (ofstream &os, const char fileName[]): StdOFStream::~StdOFStream () { if (_deleteStream) - delete _os; + delete _os; } @@ -207,7 +241,7 @@ StdOFStream::seekp (Int64 pos) } -StdOSStream::StdOSStream (): OStream ("(string)") +StdOSStream::StdOSStream (): OPENEXR_IMF_INTERNAL_NAMESPACE::OStream ("(string)") { // empty } @@ -237,4 +271,4 @@ StdOSStream::seekp (Int64 pos) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfStdIO.h b/3rdparty/openexr/IlmImf/ImfStdIO.h index b9468c204b..24c7cb5007 100644 --- a/3rdparty/openexr/IlmImf/ImfStdIO.h +++ b/3rdparty/openexr/IlmImf/ImfStdIO.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,18 +43,22 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfIO.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + #include #include -namespace Imf { + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER //------------------------------------------- // class StdIFStream -- an implementation of -// class IStream based on class std::ifstream +// class OPENEXR_IMF_INTERNAL_NAMESPACE::IStream based on class std::ifstream //------------------------------------------- -class StdIFStream: public IStream +class StdIFStream: public OPENEXR_IMF_INTERNAL_NAMESPACE::IStream { public: @@ -63,23 +67,30 @@ class StdIFStream: public IStream // The destructor will close the file. //------------------------------------------------------- + IMF_EXPORT StdIFStream (const char fileName[]); - + //--------------------------------------------------------- // A constructor that uses a std::ifstream that has already // been opened by the caller. The StdIFStream's destructor // will not close the std::ifstream. //--------------------------------------------------------- + IMF_EXPORT StdIFStream (std::ifstream &is, const char fileName[]); + IMF_EXPORT virtual ~StdIFStream (); + IMF_EXPORT virtual bool read (char c[/*n*/], int n); + IMF_EXPORT virtual Int64 tellg (); + IMF_EXPORT virtual void seekg (Int64 pos); + IMF_EXPORT virtual void clear (); private: @@ -91,10 +102,10 @@ class StdIFStream: public IStream //------------------------------------------- // class StdOFStream -- an implementation of -// class OStream based on class std::ofstream +// class OPENEXR_IMF_INTERNAL_NAMESPACE::OStream based on class std::ofstream //------------------------------------------- -class StdOFStream: public OStream +class StdOFStream: public OPENEXR_IMF_INTERNAL_NAMESPACE::OStream { public: @@ -103,8 +114,9 @@ class StdOFStream: public OStream // The destructor will close the file. //------------------------------------------------------- + IMF_EXPORT StdOFStream (const char fileName[]); - + //--------------------------------------------------------- // A constructor that uses a std::ofstream that has already @@ -112,13 +124,18 @@ class StdOFStream: public OStream // will not close the std::ofstream. //--------------------------------------------------------- + IMF_EXPORT StdOFStream (std::ofstream &os, const char fileName[]); + IMF_EXPORT virtual ~StdOFStream (); + IMF_EXPORT virtual void write (const char c[/*n*/], int n); + IMF_EXPORT virtual Int64 tellp (); + IMF_EXPORT virtual void seekp (Int64 pos); private: @@ -130,19 +147,24 @@ class StdOFStream: public OStream //------------------------------------------------ // class StdOSStream -- an implementation of class -// OStream, based on class std::ostringstream +// OPENEXR_IMF_INTERNAL_NAMESPACE::OStream, based on class std::ostringstream //------------------------------------------------ -class StdOSStream: public OStream +class StdOSStream: public OPENEXR_IMF_INTERNAL_NAMESPACE::OStream { public: + IMF_EXPORT StdOSStream (); + IMF_EXPORT virtual void write (const char c[/*n*/], int n); + IMF_EXPORT virtual Int64 tellp (); + IMF_EXPORT virtual void seekp (Int64 pos); + IMF_EXPORT std::string str () const {return _os.str();} private: @@ -151,6 +173,6 @@ class StdOSStream: public OStream }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfStringAttribute.cpp b/3rdparty/openexr/IlmImf/ImfStringAttribute.cpp index 0f74cc0284..cd241bacd4 100644 --- a/3rdparty/openexr/IlmImf/ImfStringAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfStringAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,8 +43,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -56,24 +57,24 @@ StringAttribute::staticTypeName () template <> void -StringAttribute::writeValueTo (OStream &os, int) const +StringAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { int size = _value.size(); for (int i = 0; i < size; i++) - Xdr::write (os, _value[i]); + Xdr::write (os, _value[i]); } template <> void -StringAttribute::readValueFrom (IStream &is, int size, int) +StringAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { _value.resize (size); for (int i = 0; i < size; i++) - Xdr::read (is, _value[i]); + Xdr::read (is, _value[i]); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfStringAttribute.h b/3rdparty/openexr/IlmImf/ImfStringAttribute.h index 8dc82c294c..f5d62d7b0b 100644 --- a/3rdparty/openexr/IlmImf/ImfStringAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfStringAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,24 +43,29 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfAttribute.h" #include - -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER typedef TypedAttribute StringAttribute; -template <> const char *StringAttribute::staticTypeName (); -template <> void StringAttribute::writeValueTo (OStream &, int) const; -template <> void StringAttribute::readValueFrom (IStream &, int, int); +template <> +IMF_EXPORT +const char *StringAttribute::staticTypeName (); -} // namespace Imf +template <> +IMF_EXPORT +void StringAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +template <> +IMF_EXPORT +void StringAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfStringVectorAttribute.cpp b/3rdparty/openexr/IlmImf/ImfStringVectorAttribute.cpp index 0987f34d02..88fdf8e8c1 100644 --- a/3rdparty/openexr/IlmImf/ImfStringVectorAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfStringVectorAttribute.cpp @@ -1,9 +1,9 @@ /////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007, Weta Digital Ltd -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -15,8 +15,8 @@ // distribution. // * Neither the name of Weta Digital nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -32,17 +32,19 @@ /////////////////////////////////////////////////////////////////////////// - //----------------------------------------------------------------------------- // -// class StringAttribute +// class StringVectorAttribute // //----------------------------------------------------------------------------- #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + + +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> @@ -55,7 +57,7 @@ StringVectorAttribute::staticTypeName () template <> void -StringVectorAttribute::writeValueTo (OStream &os, int) const +StringVectorAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { int size = _value.size(); @@ -63,27 +65,31 @@ StringVectorAttribute::writeValueTo (OStream &os, int) const { int strSize = _value[i].size(); Xdr::write (os, strSize); - Xdr::write (os, &_value[i][0], strSize); + Xdr::write (os, &_value[i][0], strSize); } } template <> void -StringVectorAttribute::readValueFrom (IStream &is, int size, int) +StringVectorAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { int read = 0; while (read < size) - { + { int strSize; Xdr::read (is, strSize); - read += Xdr::size(); + read += Xdr::size(); std::string str; str.resize (strSize); - - Xdr::read (is, &str[0], strSize); + + if( strSize>0 ) + { + Xdr::read (is, &str[0], strSize); + } + read += strSize; _value.push_back (str); @@ -91,4 +97,4 @@ StringVectorAttribute::readValueFrom (IStream &is, int size, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfStringVectorAttribute.h b/3rdparty/openexr/IlmImf/ImfStringVectorAttribute.h index 40fda91880..d13ef96cb1 100644 --- a/3rdparty/openexr/IlmImf/ImfStringVectorAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfStringVectorAttribute.h @@ -1,9 +1,9 @@ /////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007, Weta Digital Ltd -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -15,8 +15,8 @@ // distribution. // * Neither the name of Weta Digital nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,25 +42,33 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfAttribute.h" +#include "ImfNamespace.h" + #include #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER typedef std::vector StringVector; -typedef TypedAttribute StringVectorAttribute; -template <> const char *StringVectorAttribute::staticTypeName (); -template <> void StringVectorAttribute::writeValueTo (OStream &, int) const; -template <> void StringVectorAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute StringVectorAttribute; +template <> +IMF_EXPORT +const char *StringVectorAttribute::staticTypeName (); -} // namespace Imf +template <> +IMF_EXPORT +void StringVectorAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +template <> +IMF_EXPORT +void StringVectorAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfSystemSpecific.cpp b/3rdparty/openexr/IlmImf/ImfSystemSpecific.cpp new file mode 100644 index 0000000000..fe1d8a20be --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfSystemSpecific.cpp @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2009-2014 DreamWorks Animation LLC. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of DreamWorks Animation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfSimd.h" +#include "ImfSystemSpecific.h" +#include "ImfNamespace.h" +#include "OpenEXRConfig.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +namespace { +#if defined(IMF_HAVE_SSE2) && defined(__GNUC__) && !defined(__ANDROID__) + + // Helper functions for gcc + SSE enabled + void cpuid(int n, int &eax, int &ebx, int &ecx, int &edx) + { + __asm__ __volatile__ ( + "cpuid" + : /* Output */ "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) + : /* Input */ "a"(n) + : /* Clobber */); + } + +#else // IMF_HAVE_SSE2 && __GNUC__ + + // Helper functions for generic compiler - all disabled + void cpuid(int n, int &eax, int &ebx, int &ecx, int &edx) + { + eax = ebx = ecx = edx = 0; + } + +#endif // IMF_HAVE_SSE2 && __GNUC__ + + +#ifdef OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX + + void xgetbv(int n, int &eax, int &edx) + { + __asm__ __volatile__ ( + "xgetbv" + : /* Output */ "=a"(eax), "=d"(edx) + : /* Input */ "c"(n) + : /* Clobber */); + } + +#else // OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX + + void xgetbv(int n, int &eax, int &edx) + { + eax = edx = 0; + } + +#endif // OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX + +} // namespace + +CpuId::CpuId(): + sse2(false), + sse3(false), + ssse3(false), + sse4_1(false), + sse4_2(false), + avx(false), + f16c(false) +{ + bool osxsave = false; + int max = 0; + int eax, ebx, ecx, edx; + + cpuid(0, max, ebx, ecx, edx); + if (max > 0) + { + cpuid(1, eax, ebx, ecx, edx); + sse2 = ( edx & (1<<26) ); + sse3 = ( ecx & (1<< 0) ); + ssse3 = ( ecx & (1<< 9) ); + sse4_1 = ( ecx & (1<<19) ); + sse4_2 = ( ecx & (1<<20) ); + osxsave = ( ecx & (1<<27) ); + avx = ( ecx & (1<<28) ); + f16c = ( ecx & (1<<29) ); + + if (!osxsave) + { + avx = f16c = false; + } + else + { + xgetbv(0, eax, edx); + // eax bit 1 - SSE managed, bit 2 - AVX managed + if ((eax & 6) != 6) + { + avx = f16c = false; + } + } + } + +#if defined(IMF_HAVE_SSE2) && defined(__ANDROID__) + sse2 = true; + sse3 = true; +#ifdef __x86_64__ + ssse3 = true; + sse4_1 = true; +#endif +#endif +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfSystemSpecific.h b/3rdparty/openexr/IlmImf/ImfSystemSpecific.h new file mode 100644 index 0000000000..ad6b6197e9 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfSystemSpecific.h @@ -0,0 +1,183 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMF_COMPILER_SPECIFIC_H +#define INCLUDED_IMF_COMPILER_SPECIFIC_H + +#include "ImfNamespace.h" +#include "ImfSimd.h" +#include +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +static unsigned long systemEndianCheckValue = 0x12345678; +static unsigned long* systemEndianCheckPointer = &systemEndianCheckValue; + +// EXR files are little endian - check processor architecture is too +// (optimisation currently not supported for big endian machines) +static bool GLOBAL_SYSTEM_LITTLE_ENDIAN = + (*(unsigned char*)systemEndianCheckPointer == 0x78 ? true : false); + + +#ifdef IMF_HAVE_SSE2 + +#if defined(__GNUC__) +// Causes issues on certain gcc versions +//#define EXR_FORCEINLINE inline __attribute__((always_inline)) +#define EXR_FORCEINLINE inline +#define EXR_RESTRICT __restrict + +static void* EXRAllocAligned(size_t size, size_t alignment) +{ + // GNUC is used for things like mingw to (cross-)compile for windows +#ifdef _WIN32 + return _aligned_malloc(size, alignment); +#elif defined(__ANDROID__) + return memalign(alignment, size); +#else + void* ptr = 0; + posix_memalign(&ptr, alignment, size); + return ptr; +#endif +} + + +static void EXRFreeAligned(void* ptr) +{ +#ifdef _WIN32 + _aligned_free(ptr); +#else + free(ptr); +#endif +} + +#elif defined _MSC_VER + +#define EXR_FORCEINLINE __forceinline +#define EXR_RESTRICT __restrict + +static void* EXRAllocAligned(size_t size, size_t alignment) +{ + return _aligned_malloc(size, alignment); +} + + +static void EXRFreeAligned(void* ptr) +{ + _aligned_free(ptr); +} + +#elif defined (__INTEL_COMPILER) || \ + defined(__ICL) || \ + defined(__ICC) || \ + defined(__ECC) + +#define EXR_FORCEINLINE inline +#define EXR_RESTRICT restrict + +static void* EXRAllocAligned(size_t size, size_t alignment) +{ + return _mm_malloc(size, alignment); +} + + +static void EXRFreeAligned(void* ptr) +{ + _mm_free(ptr); +} + +#else + +// generic compiler +#define EXR_FORCEINLINE inline +#define EXR_RESTRICT + +static void* EXRAllocAligned(size_t size, size_t alignment) +{ + return malloc(size); +} + + +static void EXRFreeAligned(void* ptr) +{ + free(ptr); +} + +#endif // compiler switch + + +#else // IMF_HAVE_SSE2 + + +#define EXR_FORCEINLINE inline +#define EXR_RESTRICT + +static void* EXRAllocAligned(size_t size, size_t alignment) +{ + return malloc(size); +} + + +static void EXRFreeAligned(void* ptr) +{ + free(ptr); +} + + +#endif // IMF_HAVE_SSE2 + +// +// Simple CPUID based runtime detection of various capabilities +// +class IMF_EXPORT CpuId +{ + public: + CpuId(); + + bool sse2; + bool sse3; + bool ssse3; + bool sse4_1; + bool sse4_2; + bool avx; + bool f16c; +}; + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#endif //include guard diff --git a/3rdparty/openexr/IlmImf/ImfTestFile.cpp b/3rdparty/openexr/IlmImf/ImfTestFile.cpp index 51e18a7c65..198a4d5364 100644 --- a/3rdparty/openexr/IlmImf/ImfTestFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfTestFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,91 +45,172 @@ #include #include #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER bool -isOpenExrFile (const char fileName[], bool &tiled) +isOpenExrFile + (const char fileName[], + bool &tiled, + bool &deep, + bool &multiPart) { try { - StdIFStream is (fileName); + StdIFStream is (fileName); - int magic, version; - Xdr::read (is, magic); - Xdr::read (is, version); + int magic, version; + Xdr::read (is, magic); + Xdr::read (is, version); - tiled = isTiled (version); - return magic == MAGIC; + tiled = isTiled (version); + deep = isNonImage (version); + multiPart = isMultiPart (version); + return magic == MAGIC; } catch (...) { - tiled = false; - return false; + tiled = false; + return false; } } +bool +isOpenExrFile (const char fileName[], bool &tiled, bool &deep) +{ + bool multiPart; + return isOpenExrFile (fileName, tiled, deep, multiPart); +} + + +bool +isOpenExrFile (const char fileName[], bool &tiled) +{ + bool deep, multiPart; + return isOpenExrFile (fileName, tiled, deep, multiPart); +} + + bool isOpenExrFile (const char fileName[]) { - bool tiled; - return isOpenExrFile (fileName, tiled); + bool tiled, deep, multiPart; + return isOpenExrFile (fileName, tiled, deep, multiPart); } bool isTiledOpenExrFile (const char fileName[]) { - bool exr, tiled; - exr = isOpenExrFile (fileName, tiled); + bool exr, tiled, deep, multiPart; + exr = isOpenExrFile (fileName, tiled, deep, multiPart); return exr && tiled; } bool -isOpenExrFile (IStream &is, bool &tiled) +isDeepOpenExrFile (const char fileName[]) +{ + bool exr, tiled, deep, multiPart; + exr = isOpenExrFile (fileName, tiled, deep, multiPart); + return exr && deep; +} + + +bool +isMultiPartOpenExrFile (const char fileName[]) +{ + bool exr, tiled, deep, multiPart; + exr = isOpenExrFile (fileName, tiled, deep, multiPart); + return exr && multiPart; +} + + +bool +isOpenExrFile + (IStream &is, + bool &tiled, + bool &deep, + bool &multiPart) { try { - Int64 pos = is.tellg(); + Int64 pos = is.tellg(); - if (pos != 0) - is.seekg (0); + if (pos != 0) + is.seekg (0); - int magic, version; - Xdr::read (is, magic); - Xdr::read (is, version); + int magic, version; + Xdr::read (is, magic); + Xdr::read (is, version); - is.seekg (pos); + is.seekg (pos); - tiled = isTiled (version); - return magic == MAGIC; + tiled = isTiled (version); + deep = isNonImage (version); + multiPart = isMultiPart (version); + return magic == MAGIC; } catch (...) { - is.clear(); - tiled = false; - return false; + is.clear(); + tiled = false; + return false; } } bool -isOpenExrFile (IStream &is) +isOpenExrFile (IStream &is, bool &tiled, bool &deep) +{ + bool multiPart; + return isOpenExrFile (is, tiled, deep, multiPart); +} + + +bool +isOpenExrFile (IStream &is, bool &tiled) { - bool tiled; - return isOpenExrFile (is, tiled); + bool deep, multiPart; + return isOpenExrFile (is, tiled, deep, multiPart); } bool -isTiledOpenExrFile (IStream &is) +isOpenExrFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is) { - bool exr, tiled; - exr = isOpenExrFile (is, tiled); + bool tiled, deep, multiPart; + return isOpenExrFile (is, tiled, deep, multiPart); +} + + +bool +isTiledOpenExrFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is) +{ + bool exr, tiled, deep, multiPart; + exr = isOpenExrFile (is, tiled, deep, multiPart); return exr && tiled; } -} // namespace Imf + +bool +isDeepOpenExrFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is) +{ + bool exr, tiled, deep, multiPart; + exr = isOpenExrFile (is, tiled, deep, multiPart); + return exr && deep; +} + + +bool +isMultiPartOpenExrFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is) +{ + bool exr, tiled, deep, multiPart; + exr = isOpenExrFile (is, tiled, deep, multiPart); + return exr && multiPart; +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTestFile.h b/3rdparty/openexr/IlmImf/ImfTestFile.h index e7e5065723..d02d3bc742 100644 --- a/3rdparty/openexr/IlmImf/ImfTestFile.h +++ b/3rdparty/openexr/IlmImf/ImfTestFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,20 +44,54 @@ // //----------------------------------------------------------------------------- +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +IMF_EXPORT bool isOpenExrFile (const char fileName[]); + +IMF_EXPORT bool isOpenExrFile (const char fileName[], + bool &isTiled); + +IMF_EXPORT bool isOpenExrFile (const char fileName[], + bool &isTiled, + bool &isDeep); + +IMF_EXPORT bool isOpenExrFile (const char fileName[], + bool &isTiled, + bool &isDeep, + bool &isMultiPart); + +IMF_EXPORT bool isTiledOpenExrFile (const char fileName[]); + +IMF_EXPORT bool isDeepOpenExrFile (const char fileName[]); + +IMF_EXPORT bool isMultiPartOpenExrFile (const char fileName[]); + +IMF_EXPORT bool isOpenExrFile (IStream &is); + +IMF_EXPORT bool isOpenExrFile (IStream &is, + bool &isTiled); + +IMF_EXPORT bool isOpenExrFile (IStream &is, + bool &isTiled, + bool &isDeep); -namespace Imf { +IMF_EXPORT bool isOpenExrFile (IStream &is, + bool &isTiled, + bool &isDeep, + bool &isMultiPart); -class IStream; +IMF_EXPORT bool isTiledOpenExrFile (IStream &is); +IMF_EXPORT bool isDeepOpenExrFile (IStream &is); -bool isOpenExrFile (const char fileName[], bool &isTiled); -bool isOpenExrFile (const char fileName[]); -bool isTiledOpenExrFile (const char fileName[]); -bool isOpenExrFile (IStream &is, bool &isTiled); -bool isOpenExrFile (IStream &is); -bool isTiledOpenExrFile (IStream &is); +IMF_EXPORT bool isMultiPartOpenExrFile (IStream &is); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfThreading.cpp b/3rdparty/openexr/IlmImf/ImfThreading.cpp index b69741f9e0..a3cf3839c2 100644 --- a/3rdparty/openexr/IlmImf/ImfThreading.cpp +++ b/3rdparty/openexr/IlmImf/ImfThreading.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2005, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -38,24 +38,25 @@ // //----------------------------------------------------------------------------- -#include "IlmThreadPool.h" #include "ImfThreading.h" +#include "IlmThreadPool.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER int globalThreadCount () { - return IlmThread::ThreadPool::globalThreadPool().numThreads(); + return ILMTHREAD_NAMESPACE::ThreadPool::globalThreadPool().numThreads(); } void setGlobalThreadCount (int count) { - IlmThread::ThreadPool::globalThreadPool().setNumThreads (count); + ILMTHREAD_NAMESPACE::ThreadPool::globalThreadPool().setNumThreads (count); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfThreading.h b/3rdparty/openexr/IlmImf/ImfThreading.h index efd9a6520b..4d1db040d5 100644 --- a/3rdparty/openexr/IlmImf/ImfThreading.h +++ b/3rdparty/openexr/IlmImf/ImfThreading.h @@ -2,9 +2,9 @@ // // Copyright (c) 2005, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -35,6 +35,9 @@ #ifndef INCLUDED_IMF_THREADING_H #define INCLUDED_IMF_THREADING_H +#include "ImfExport.h" +#include "ImfNamespace.h" + //----------------------------------------------------------------------------- // // Threading support for the IlmImf library @@ -50,7 +53,7 @@ // done concurrently through pinelining. If there are two or more // worker threads, then pipelining as well as concurrent compression // of multiple blocks can be performed. -// +// // Threading in the Imf library is controllable at two granularities: // // * The functions in this file query and control the total number @@ -69,24 +72,24 @@ // //----------------------------------------------------------------------------- -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER //----------------------------------------------------------------------------- // Return the number of Imf-global worker threads used for parallel // compression and decompression of OpenEXR files. //----------------------------------------------------------------------------- - -int globalThreadCount (); + +IMF_EXPORT int globalThreadCount (); //----------------------------------------------------------------------------- // Change the number of Imf-global worker threads //----------------------------------------------------------------------------- -void setGlobalThreadCount (int count); +IMF_EXPORT void setGlobalThreadCount (int count); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfTileDescription.h b/3rdparty/openexr/IlmImf/ImfTileDescription.h index 9534133c0a..7b219c8445 100644 --- a/3rdparty/openexr/IlmImf/ImfTileDescription.h +++ b/3rdparty/openexr/IlmImf/ImfTileDescription.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,8 +41,9 @@ // class TileDescription and enum LevelMode // //----------------------------------------------------------------------------- +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER enum LevelMode @@ -50,7 +51,7 @@ enum LevelMode ONE_LEVEL = 0, MIPMAP_LEVELS = 1, RIPMAP_LEVELS = 2, - + NUM_LEVELMODES // number of different level modes }; @@ -72,31 +73,35 @@ class TileDescription unsigned int ySize; // size of a tile in the y dimension LevelMode mode; LevelRoundingMode roundingMode; - + TileDescription (unsigned int xs = 32, - unsigned int ys = 32, + unsigned int ys = 32, LevelMode m = ONE_LEVEL, - LevelRoundingMode r = ROUND_DOWN) + LevelRoundingMode r = ROUND_DOWN) : xSize (xs), - ySize (ys), - mode (m), - roundingMode (r) + ySize (ys), + mode (m), + roundingMode (r) { - // empty + // empty } bool operator == (const TileDescription &other) const { - return xSize == other.xSize && - ySize == other.ySize && - mode == other.mode && - roundingMode == other.roundingMode; + return xSize == other.xSize && + ySize == other.ySize && + mode == other.mode && + roundingMode == other.roundingMode; } }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfTileDescriptionAttribute.cpp b/3rdparty/openexr/IlmImf/ImfTileDescriptionAttribute.cpp index e2545f568b..18aead598e 100644 --- a/3rdparty/openexr/IlmImf/ImfTileDescriptionAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfTileDescriptionAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,8 +42,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -55,7 +56,7 @@ TileDescriptionAttribute::staticTypeName () template <> void -TileDescriptionAttribute::writeValueTo (OStream &os, int) const +TileDescriptionAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.xSize); Xdr::write (os, _value.ySize); @@ -67,9 +68,9 @@ TileDescriptionAttribute::writeValueTo (OStream &os, int) const template <> void -TileDescriptionAttribute::readValueFrom (IStream &is, - int, - int) +TileDescriptionAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + int size, + int version) { Xdr::read (is, _value.xSize); Xdr::read (is, _value.ySize); @@ -78,8 +79,8 @@ TileDescriptionAttribute::readValueFrom (IStream &is, Xdr::read (is, tmp); _value.mode = LevelMode (tmp & 0x0f); _value.roundingMode = LevelRoundingMode ((tmp >> 4) & 0x0f); - + } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTileDescriptionAttribute.h b/3rdparty/openexr/IlmImf/ImfTileDescriptionAttribute.h index cb1ff2b0aa..a8b69b9200 100644 --- a/3rdparty/openexr/IlmImf/ImfTileDescriptionAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfTileDescriptionAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,32 +42,31 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfAttribute.h" +#include "ImfTileDescription.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER - -typedef TypedAttribute TileDescriptionAttribute; +typedef TypedAttribute TileDescriptionAttribute; template <> +IMF_EXPORT const char * TileDescriptionAttribute::staticTypeName (); template <> +IMF_EXPORT void -TileDescriptionAttribute::writeValueTo (OStream &, int) const; +TileDescriptionAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; template <> +IMF_EXPORT void -TileDescriptionAttribute::readValueFrom (IStream &, int, int); - +TileDescriptionAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); -} // namespace Imf -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfTileOffsets.cpp b/3rdparty/openexr/IlmImf/ImfTileOffsets.cpp index 0eba39bca0..b0b40f637c 100644 --- a/3rdparty/openexr/IlmImf/ImfTileOffsets.cpp +++ b/3rdparty/openexr/IlmImf/ImfTileOffsets.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,13 +43,15 @@ #include #include #include "Iex.h" +#include "ImfNamespace.h" +#include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER TileOffsets::TileOffsets (LevelMode mode, - int numXLevels, int numYLevels, - const int *numXTiles, const int *numYTiles) + int numXLevels, int numYLevels, + const int *numXTiles, const int *numYTiles) : _mode (mode), _numXLevels (numXLevels), @@ -67,7 +69,7 @@ TileOffsets::TileOffsets (LevelMode mode, _offsets[l].resize (numYTiles[l]); for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) - { + { _offsets[l][dy].resize (numXTiles[l]); } } @@ -77,20 +79,23 @@ TileOffsets::TileOffsets (LevelMode mode, _offsets.resize (_numXLevels * _numYLevels); - for (unsigned int ly = 0; ly < _numYLevels; ++ly) + for (int ly = 0; ly < _numYLevels; ++ly) { - for (unsigned int lx = 0; lx < _numXLevels; ++lx) + for (int lx = 0; lx < _numXLevels; ++lx) { int l = ly * _numXLevels + lx; _offsets[l].resize (numYTiles[ly]); - for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) + for (size_t dy = 0; dy < _offsets[l].size(); ++dy) { _offsets[l][dy].resize (numXTiles[lx]); } } } break; + + case NUM_LEVELMODES : + throw IEX_NAMESPACE::ArgExc("Bad initialisation of TileOffsets object"); } } @@ -99,55 +104,76 @@ bool TileOffsets::anyOffsetsAreInvalid () const { for (unsigned int l = 0; l < _offsets.size(); ++l) - for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) - for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) - if (_offsets[l][dy][dx] <= 0) - return true; - + for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) + for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) + if (_offsets[l][dy][dx] <= 0) + return true; + return false; } void -TileOffsets::findTiles (IStream &is) +TileOffsets::findTiles (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, bool isMultiPartFile, bool isDeep, bool skipOnly) { for (unsigned int l = 0; l < _offsets.size(); ++l) { - for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) - { - for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) - { - Int64 tileOffset = is.tellg(); + for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) + { + for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) + { + Int64 tileOffset = is.tellg(); - int tileX; - Xdr::read (is, tileX); + if (isMultiPartFile) + { + int partNumber; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, partNumber); + } - int tileY; - Xdr::read (is, tileY); + int tileX; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, tileX); - int levelX; - Xdr::read (is, levelX); + int tileY; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, tileY); - int levelY; - Xdr::read (is, levelY); + int levelX; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, levelX); - int dataSize; - Xdr::read (is, dataSize); + int levelY; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, levelY); - Xdr::skip (is, dataSize); + if(isDeep) + { + Int64 packed_offset_table_size; + Int64 packed_sample_size; + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_offset_table_size); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_sample_size); + + // next Int64 is unpacked sample size - skip that too + Xdr::skip (is, packed_offset_table_size+packed_sample_size+8); + + }else{ + + int dataSize; + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, dataSize); + + Xdr::skip (is, dataSize); + } + if (skipOnly) continue; - if (!isValidTile(tileX, tileY, levelX, levelY)) - return; + if (!isValidTile(tileX, tileY, levelX, levelY)) + return; - operator () (tileX, tileY, levelX, levelY) = tileOffset; - } - } + operator () (tileX, tileY, levelX, levelY) = tileOffset; + } + } } } void -TileOffsets::reconstructFromFile (IStream &is) +TileOffsets::reconstructFromFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,bool isMultiPart,bool isDeep) { // // Try to reconstruct a missing tile offset table by sequentially @@ -159,14 +185,14 @@ TileOffsets::reconstructFromFile (IStream &is) try { - findTiles (is); + findTiles (is,isMultiPart,isDeep,false); } catch (...) { // // Suppress all exceptions. This function is called only to - // reconstruct the tile offset table for incomplete files, - // and exceptions are likely. + // reconstruct the tile offset table for incomplete files, + // and exceptions are likely. // } @@ -176,16 +202,16 @@ TileOffsets::reconstructFromFile (IStream &is) void -TileOffsets::readFrom (IStream &is, bool &complete) +TileOffsets::readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, bool &complete,bool isMultiPartFile, bool isDeep) { // // Read in the tile offsets from the file's tile offset table // for (unsigned int l = 0; l < _offsets.size(); ++l) - for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) - for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) - Xdr::read (is, _offsets[l][dy][dx]); + for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) + for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, _offsets[l][dy][dx]); // // Check if any tile offsets are invalid. @@ -203,48 +229,182 @@ TileOffsets::readFrom (IStream &is, bool &complete) if (anyOffsetsAreInvalid()) { - complete = false; - reconstructFromFile (is); + complete = false; + reconstructFromFile (is,isMultiPartFile,isDeep); } else { - complete = true; + complete = true; } } +void +TileOffsets::readFrom (std::vector chunkOffsets,bool &complete) +{ + size_t totalSize = 0; + + for (unsigned int l = 0; l < _offsets.size(); ++l) + for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) + totalSize += _offsets[l][dy].size(); + + if (chunkOffsets.size() != totalSize) + throw IEX_NAMESPACE::ArgExc ("Wrong offset count, not able to read from this array"); + + + + int pos = 0; + for (size_t l = 0; l < _offsets.size(); ++l) + for (size_t dy = 0; dy < _offsets[l].size(); ++dy) + for (size_t dx = 0; dx < _offsets[l][dy].size(); ++dx) + { + _offsets[l][dy][dx] = chunkOffsets[pos]; + pos++; + } + + complete = !anyOffsetsAreInvalid(); + +} + + Int64 -TileOffsets::writeTo (OStream &os) const +TileOffsets::writeTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os) const { // // Write the tile offset table to the file, and // return the position of the start of the table // in the file. // - + Int64 pos = os.tellp(); if (pos == -1) - Iex::throwErrnoExc ("Cannot determine current file position (%T)."); + IEX_NAMESPACE::throwErrnoExc ("Cannot determine current file position (%T)."); for (unsigned int l = 0; l < _offsets.size(); ++l) - for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) - for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) - Xdr::write (os, _offsets[l][dy][dx]); + for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) + for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write (os, _offsets[l][dy][dx]); return pos; } +namespace { +struct tilepos{ + Int64 filePos; + int dx; + int dy; + int l; + bool operator <(const tilepos & other) const + { + return filePos < other.filePos; + } +}; +} +//------------------------------------- +// fill array with tile coordinates in the order they appear in the file +// +// each input array must be of size (totalTiles) +// +// +// if the tile order is not RANDOM_Y, it is more efficient to compute the +// tile ordering rather than using this function +// +//------------------------------------- +void TileOffsets::getTileOrder(int dx_table[],int dy_table[],int lx_table[],int ly_table[]) const +{ + // + // helper class + // + + // how many entries? + size_t entries=0; + for (unsigned int l = 0; l < _offsets.size(); ++l) + for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) + entries+=_offsets[l][dy].size(); + + std::vector table(entries); + + size_t i = 0; + for (unsigned int l = 0; l < _offsets.size(); ++l) + for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy) + for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx) + { + table[i].filePos = _offsets[l][dy][dx]; + table[i].dx = dx; + table[i].dy = dy; + table[i].l = l; + + ++i; + + } + + std::sort(table.begin(),table.end()); + + // + // write out the values + // + + // pass 1: write out dx and dy, since these are independent of level mode + + for(size_t i=0;i 0 && - _offsets[0].size() > dy && - _offsets[0][dy].size() > dx) - { + ly == 0 && + _offsets.size() > 0 && + int(_offsets[0].size()) > dy && + int(_offsets[0][dy].size()) > dx) + { return true; - } + } break; case MIPMAP_LEVELS: if (lx < _numXLevels && - ly < _numYLevels && - _offsets.size() > lx && - _offsets[lx].size() > dy && - _offsets[lx][dy].size() > dx) - { + ly < _numYLevels && + int(_offsets.size()) > lx && + int(_offsets[lx].size()) > dy && + int(_offsets[lx][dy].size()) > dx) + { return true; - } + } break; case RIPMAP_LEVELS: if (lx < _numXLevels && - ly < _numYLevels && - _offsets.size() > lx + ly * _numXLevels && - _offsets[lx + ly * _numXLevels].size() > dy && - _offsets[lx + ly * _numXLevels][dy].size() > dx) - { + ly < _numYLevels && + (_offsets.size() > (size_t) lx+ ly * (size_t) _numXLevels) && + int(_offsets[lx + ly * _numXLevels].size()) > dy && + int(_offsets[lx + ly * _numXLevels][dy].size()) > dx) + { return true; - } + } break; @@ -297,7 +458,7 @@ TileOffsets::isValidTile (int dx, int dy, int lx, int ly) const return false; } - + return false; } @@ -330,7 +491,7 @@ TileOffsets::operator () (int dx, int dy, int lx, int ly) default: - throw Iex::ArgExc ("Unknown LevelMode format."); + throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format."); } } @@ -370,7 +531,7 @@ TileOffsets::operator () (int dx, int dy, int lx, int ly) const default: - throw Iex::ArgExc ("Unknown LevelMode format."); + throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format."); } } @@ -381,5 +542,11 @@ TileOffsets::operator () (int dx, int dy, int l) const return operator () (dx, dy, l, l); } +const std::vector > >& +TileOffsets::getOffsets() const +{ + return _offsets; +} + -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTileOffsets.h b/3rdparty/openexr/IlmImf/ImfTileOffsets.h index 13026c9f63..383dfc44c3 100644 --- a/3rdparty/openexr/IlmImf/ImfTileOffsets.h +++ b/3rdparty/openexr/IlmImf/ImfTileOffsets.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,66 +42,96 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfTileDescription.h" +#include "ImfInt64.h" #include +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" -namespace Imf { - -class IStream; -class OStream; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class TileOffsets { public: + IMF_EXPORT TileOffsets (LevelMode mode = ONE_LEVEL, - int numXLevels = 0, - int numYLevels = 0, - const int *numXTiles = 0, - const int *numYTiles = 0); + int numXLevels = 0, + int numYLevels = 0, + const int *numXTiles = 0, + const int *numYTiles = 0); // -------- // File I/O // -------- - void readFrom (IStream &is, bool &complete); - Int64 writeTo (OStream &os) const; + IMF_EXPORT + void readFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, bool &complete,bool isMultiPart,bool isDeep); + IMF_EXPORT + void readFrom (std::vector chunkOffsets,bool &complete); + IMF_EXPORT + Int64 writeTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os) const; //----------------------------------------------------------- // Test if the tileOffsets array is empty (all entries are 0) //----------------------------------------------------------- + IMF_EXPORT bool isEmpty () const; - - + + + + //----------------------------------------------------------- + // populate 'list' with tiles coordinates in the order they appear + // in the offset table (assumes full table! + // each array myst be at leat totalTiles long + //----------------------------------------------------------- + IMF_EXPORT + void getTileOrder(int dx_table[], int dy_table[], int lx_table[], int ly_table[]) const; + + //----------------------- // Access to the elements //----------------------- + IMF_EXPORT Int64 & operator () (int dx, int dy, int lx, int ly); + IMF_EXPORT Int64 & operator () (int dx, int dy, int l); + IMF_EXPORT const Int64 & operator () (int dx, int dy, int lx, int ly) const; + IMF_EXPORT const Int64 & operator () (int dx, int dy, int l) const; - + IMF_EXPORT + bool isValidTile (int dx, int dy, int lx, int ly) const; + IMF_EXPORT + const std::vector > >& getOffsets() const; + private: - void findTiles (IStream &is); - void reconstructFromFile (IStream &is); - bool readTile (IStream &is); + void findTiles (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, bool isMultiPartFile, + bool isDeep, + bool skipOnly); + void reconstructFromFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,bool isMultiPartFile,bool isDeep); + bool readTile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is); bool anyOffsetsAreInvalid () const; - bool isValidTile (int dx, int dy, int lx, int ly) const; LevelMode _mode; int _numXLevels; int _numYLevels; std::vector > > _offsets; + }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfTiledInputFile.cpp b/3rdparty/openexr/IlmImf/ImfTiledInputFile.cpp index 69cb276baf..b5fbeb7043 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledInputFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfTiledInputFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -38,19 +38,21 @@ // //----------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include -#include "ImathBox.h" -#include -#include -#include -#include -#include +#include "ImfTiledInputFile.h" +#include "ImfTileDescriptionAttribute.h" +#include "ImfChannelList.h" +#include "ImfMisc.h" +#include "ImfTiledMisc.h" +#include "ImfStdIO.h" +#include "ImfCompressor.h" +#include "ImfXdr.h" +#include "ImfConvert.h" +#include "ImfVersion.h" +#include "ImfTileOffsets.h" +#include "ImfThreading.h" +#include "ImfPartType.h" +#include "ImfMultiPartInputFile.h" +#include "ImfInputStreamMutex.h" #include "IlmThreadPool.h" #include "IlmThreadSemaphore.h" #include "IlmThreadMutex.h" @@ -60,22 +62,23 @@ #include #include #include +#include "ImfInputPartData.h" +#include "ImfNamespace.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -namespace Imf { - -using Imath::Box2i; -using Imath::V2i; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::V2i; using std::string; using std::vector; using std::min; using std::max; -using IlmThread::Mutex; -using IlmThread::Lock; -using IlmThread::Semaphore; -using IlmThread::Task; -using IlmThread::TaskGroup; -using IlmThread::ThreadPool; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using ILMTHREAD_NAMESPACE::Semaphore; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; namespace { @@ -157,6 +160,7 @@ struct TileBuffer TileBuffer::TileBuffer (Compressor *comp): uncompressedData (0), + buffer (0), dataSize (0), compressor (comp), format (defaultFormat (compressor)), @@ -180,6 +184,9 @@ TileBuffer::~TileBuffer () } // namespace +class MultiPartInputFile; + + // // struct TiledInputFile::Data stores things that will be // needed between calls to readTile() @@ -187,61 +194,70 @@ TileBuffer::~TileBuffer () struct TiledInputFile::Data: public Mutex { - Header header; // the image header - TileDescription tileDesc; // describes the tile layout - int version; // file's version - FrameBuffer frameBuffer; // framebuffer to write into - LineOrder lineOrder; // the file's lineorder - int minX; // data window's min x coord - int maxX; // data window's max x coord - int minY; // data window's min y coord - int maxY; // data window's max x coord + Header header; // the image header + TileDescription tileDesc; // describes the tile layout + int version; // file's version + FrameBuffer frameBuffer; // framebuffer to write into + LineOrder lineOrder; // the file's lineorder + int minX; // data window's min x coord + int maxX; // data window's max x coord + int minY; // data window's min y coord + int maxY; // data window's max x coord - int numXLevels; // number of x levels - int numYLevels; // number of y levels - int * numXTiles; // number of x tiles at a level - int * numYTiles; // number of y tiles at a level + int numXLevels; // number of x levels + int numYLevels; // number of y levels + int * numXTiles; // number of x tiles at a level + int * numYTiles; // number of y tiles at a level - TileOffsets tileOffsets; // stores offsets in file for - // each tile + TileOffsets tileOffsets; // stores offsets in file for + // each tile - bool fileIsComplete; // True if no tiles are missing - // in the file + bool fileIsComplete; // True if no tiles are missing + // in the file - Int64 currentPosition; // file offset for current tile, - // used to prevent unnecessary - // seeking + vector slices; // info about channels in file - vector slices; // info about channels in file - IStream * is; // file stream to read from + size_t bytesPerPixel; // size of an uncompressed pixel - bool deleteStream; // should we delete the stream - // ourselves? or does someone - // else do it? + size_t maxBytesPerTileLine; // combined size of a line + // over all channels - size_t bytesPerPixel; // size of an uncompressed pixel + int partNumber; // part number - size_t maxBytesPerTileLine; // combined size of a line - // over all channels + bool multiPartBackwardSupport; // if we are reading a multipart file + // using OpenEXR 1.7 API + int numThreads; // number of threads - vector tileBuffers; // each holds a single tile - size_t tileBufferSize; // size of the tile buffers + MultiPartInputFile* multiPartFile; // the MultiPartInputFile used to + // support backward compatibility + + vector tileBuffers; // each holds a single tile + size_t tileBufferSize; // size of the tile buffers - Data (bool deleteStream, int numThreads); + bool memoryMapped; // if the stream is memory mapped + + InputStreamMutex * _streamData; + bool _deleteStream; + + Data (int numThreads); ~Data (); inline TileBuffer * getTileBuffer (int number); - // hash function from tile indices - // into our vector of tile buffers + // hash function from tile indices + // into our vector of tile buffers }; -TiledInputFile::Data::Data (bool del, int numThreads): +TiledInputFile::Data::Data (int numThreads): numXTiles (0), numYTiles (0), - is (0), - deleteStream (del) + partNumber (-1), + multiPartBackwardSupport(false), + numThreads(numThreads), + memoryMapped(false), + _streamData(NULL), + _deleteStream(false) { // // We need at least one tileBuffer, but if threading is used, @@ -257,11 +273,11 @@ TiledInputFile::Data::~Data () delete [] numXTiles; delete [] numYTiles; - if (deleteStream) - delete is; - for (size_t i = 0; i < tileBuffers.size(); i++) delete tileBuffers[i]; + + if (multiPartBackwardSupport) + delete multiPartFile; } @@ -275,9 +291,10 @@ TiledInputFile::Data::getTileBuffer (int number) namespace { void -readTileData (TiledInputFile::Data *ifd, - int dx, int dy, - int lx, int ly, +readTileData (InputStreamMutex *streamData, + TiledInputFile::Data *ifd, + int dx, int dy, + int lx, int ly, char *&buffer, int &dataSize) { @@ -292,103 +309,144 @@ readTileData (TiledInputFile::Data *ifd, // Look up the location for this tile in the Index and // seek to that position if necessary // - + Int64 tileOffset = ifd->tileOffsets (dx, dy, lx, ly); if (tileOffset == 0) { - THROW (Iex::InputExc, "Tile (" << dx << ", " << dy << ", " << - lx << ", " << ly << ") is missing."); + THROW (IEX_NAMESPACE::InputExc, "Tile (" << dx << ", " << dy << ", " << + lx << ", " << ly << ") is missing."); } - if (ifd->currentPosition != tileOffset) - ifd->is->seekg (tileOffset); + + // + // In a multi-part file, the next chunk does not need to + // belong to the same part, so we have to compare the + // offset here. + // + + if (!isMultiPart(ifd->version)) + { + if (streamData->currentPosition != tileOffset) + streamData->is->seekg (tileOffset); + } + else + { + // + // In a multi-part file, the file pointer may be moved by other + // parts, so we have to ask tellg() where we are. + // + if (streamData->is->tellg() != tileOffset) + streamData->is->seekg (tileOffset); + } // // Read the first few bytes of the tile (the header). // Verify that the tile coordinates and the level number // are correct. // - + int tileXCoord, tileYCoord, levelX, levelY; - Xdr::read (*ifd->is, tileXCoord); - Xdr::read (*ifd->is, tileYCoord); - Xdr::read (*ifd->is, levelX); - Xdr::read (*ifd->is, levelY); - Xdr::read (*ifd->is, dataSize); + if (isMultiPart(ifd->version)) + { + int partNumber; + Xdr::read (*streamData->is, partNumber); + if (partNumber != ifd->partNumber) + { + THROW (IEX_NAMESPACE::ArgExc, "Unexpected part number " << partNumber + << ", should be " << ifd->partNumber << "."); + } + } + + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, tileXCoord); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, tileYCoord); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, levelX); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, levelY); + OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (*streamData->is, dataSize); if (tileXCoord != dx) - throw Iex::InputExc ("Unexpected tile x coordinate."); + throw IEX_NAMESPACE::InputExc ("Unexpected tile x coordinate."); if (tileYCoord != dy) - throw Iex::InputExc ("Unexpected tile y coordinate."); + throw IEX_NAMESPACE::InputExc ("Unexpected tile y coordinate."); if (levelX != lx) - throw Iex::InputExc ("Unexpected tile x level number coordinate."); + throw IEX_NAMESPACE::InputExc ("Unexpected tile x level number coordinate."); if (levelY != ly) - throw Iex::InputExc ("Unexpected tile y level number coordinate."); + throw IEX_NAMESPACE::InputExc ("Unexpected tile y level number coordinate."); if (dataSize > (int) ifd->tileBufferSize) - throw Iex::InputExc ("Unexpected tile block length."); + throw IEX_NAMESPACE::InputExc ("Unexpected tile block length."); // // Read the pixel data. // - if (ifd->is->isMemoryMapped ()) - buffer = ifd->is->readMemoryMapped (dataSize); + if (streamData->is->isMemoryMapped ()) + buffer = streamData->is->readMemoryMapped (dataSize); else - ifd->is->read (buffer, dataSize); + streamData->is->read (buffer, dataSize); // // Keep track of which tile is the next one in // the file, so that we can avoid redundant seekg() // operations (seekg() can be fairly expensive). // - - ifd->currentPosition = tileOffset + 5 * Xdr::size() + dataSize; + + streamData->currentPosition = tileOffset + 5 * Xdr::size() + dataSize; } void -readNextTileData (TiledInputFile::Data *ifd, - int &dx, int &dy, - int &lx, int &ly, +readNextTileData (InputStreamMutex *streamData, + TiledInputFile::Data *ifd, + int &dx, int &dy, + int &lx, int &ly, char * & buffer, - int &dataSize) + int &dataSize) { // // Read the next tile block from the file // + if(isMultiPart(ifd->version)) + { + int part; + Xdr::read (*streamData->is, part); + if(part!=ifd->partNumber) + { + throw IEX_NAMESPACE::InputExc("Unexpected part number in readNextTileData"); + } + } + // // Read the first few bytes of the tile (the header). // - Xdr::read (*ifd->is, dx); - Xdr::read (*ifd->is, dy); - Xdr::read (*ifd->is, lx); - Xdr::read (*ifd->is, ly); - Xdr::read (*ifd->is, dataSize); + Xdr::read (*streamData->is, dx); + Xdr::read (*streamData->is, dy); + Xdr::read (*streamData->is, lx); + Xdr::read (*streamData->is, ly); + Xdr::read (*streamData->is, dataSize); if (dataSize > (int) ifd->tileBufferSize) - throw Iex::InputExc ("Unexpected tile block length."); - + throw IEX_NAMESPACE::InputExc ("Unexpected tile block length."); + // // Read the pixel data. // - ifd->is->read (buffer, dataSize); - + streamData->is->read (buffer, dataSize); + // // Keep track of which tile is the next one in // the file, so that we can avoid redundant seekg() // operations (seekg() can be fairly expensive). // - ifd->currentPosition += 5 * Xdr::size() + dataSize; + streamData->currentPosition += 5 * Xdr::size() + dataSize; } @@ -403,12 +461,12 @@ class TileBufferTask : public Task TileBufferTask (TaskGroup *group, TiledInputFile::Data *ifd, - TileBuffer *tileBuffer); - + TileBuffer *tileBuffer); + virtual ~TileBufferTask (); virtual void execute (); - + private: TiledInputFile::Data * _ifd; @@ -447,34 +505,35 @@ TileBufferTask::execute () // // Calculate information about the tile // - - Box2i tileRange = Imf::dataWindowForTile (_ifd->tileDesc, - _ifd->minX, _ifd->maxX, - _ifd->minY, _ifd->maxY, - _tileBuffer->dx, - _tileBuffer->dy, - _tileBuffer->lx, - _tileBuffer->ly); + + Box2i tileRange = OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile ( + _ifd->tileDesc, + _ifd->minX, _ifd->maxX, + _ifd->minY, _ifd->maxY, + _tileBuffer->dx, + _tileBuffer->dy, + _tileBuffer->lx, + _tileBuffer->ly); int numPixelsPerScanLine = tileRange.max.x - tileRange.min.x + 1; - + int numPixelsInTile = numPixelsPerScanLine * (tileRange.max.y - tileRange.min.y + 1); - + int sizeOfTile = _ifd->bytesPerPixel * numPixelsInTile; - - + + // // Uncompress the data, if necessary // - + if (_tileBuffer->compressor && _tileBuffer->dataSize < sizeOfTile) { _tileBuffer->format = _tileBuffer->compressor->format(); _tileBuffer->dataSize = _tileBuffer->compressor->uncompressTile - (_tileBuffer->buffer, _tileBuffer->dataSize, - tileRange, _tileBuffer->uncompressedData); + (_tileBuffer->buffer, _tileBuffer->dataSize, + tileRange, _tileBuffer->uncompressedData); } else { @@ -482,54 +541,54 @@ TileBufferTask::execute () // If the line is uncompressed, it's in XDR format, // regardless of the compressor's output format. // - + _tileBuffer->format = Compressor::XDR; _tileBuffer->uncompressedData = _tileBuffer->buffer; } - + // // Convert the tile of pixel data back from the machine-independent - // representation, and store the result in the frame buffer. + // representation, and store the result in the frame buffer. // - + const char *readPtr = _tileBuffer->uncompressedData; // points to where we // read from in the // tile block - + // // Iterate over the scan lines in the tile. // - + for (int y = tileRange.min.y; y <= tileRange.max.y; ++y) { // // Iterate over all image channels. // - + for (unsigned int i = 0; i < _ifd->slices.size(); ++i) { const TInSliceInfo &slice = _ifd->slices[i]; - + // // These offsets are used to facilitate both // absolute and tile-relative pixel coordinates. // - + int xOffset = slice.xTileCoords * tileRange.min.x; int yOffset = slice.yTileCoords * tileRange.min.y; - + // // Fill the frame buffer with pixel data. // - + if (slice.skip) { // // The file contains data for this channel, but // the frame buffer contains no slice for this channel. // - + skipChannel (readPtr, slice.typeInFile, numPixelsPerScanLine); } @@ -538,7 +597,7 @@ TileBufferTask::execute () // // The frame buffer contains a slice for this channel. // - + char *writePtr = slice.base + (y - yOffset) * slice.yStride + (tileRange.min.x - xOffset) * @@ -546,7 +605,7 @@ TileBufferTask::execute () char *endPtr = writePtr + (numPixelsPerScanLine - 1) * slice.xStride; - + copyIntoFrameBuffer (readPtr, writePtr, endPtr, slice.xStride, slice.fill, slice.fillValue, @@ -579,6 +638,7 @@ TileBufferTask::execute () TileBufferTask * newTileBufferTask (TaskGroup *group, + InputStreamMutex *streamData, TiledInputFile::Data *ifd, int number, int dx, int dy, @@ -596,29 +656,29 @@ newTileBufferTask try { - tileBuffer->wait(); - - tileBuffer->dx = dx; - tileBuffer->dy = dy; - tileBuffer->lx = lx; - tileBuffer->ly = ly; - - tileBuffer->uncompressedData = 0; - - readTileData (ifd, dx, dy, lx, ly, - tileBuffer->buffer, - tileBuffer->dataSize); + tileBuffer->wait(); + + tileBuffer->dx = dx; + tileBuffer->dy = dy; + tileBuffer->lx = lx; + tileBuffer->ly = ly; + + tileBuffer->uncompressedData = 0; + + readTileData (streamData, ifd, dx, dy, lx, ly, + tileBuffer->buffer, + tileBuffer->dataSize); } catch (...) { - // - // Reading from the file caused an exception. - // Signal that the tile buffer is free, and - // re-throw the exception. - // - - tileBuffer->post(); - throw; + // + // Reading from the file caused an exception. + // Signal that the tile buffer is free, and + // re-throw the exception. + // + + tileBuffer->post(); + throw; } return new TileBufferTask (group, ifd, tileBuffer); @@ -629,92 +689,229 @@ newTileBufferTask TiledInputFile::TiledInputFile (const char fileName[], int numThreads): - _data (new Data (true, numThreads)) + _data (new Data (numThreads)) { + _data->_streamData=NULL; + _data->_deleteStream=true; + // // This constructor is called when a user // explicitly wants to read a tiled file. // + + IStream* is = 0; try { - _data->is = new StdIFStream (fileName); - _data->header.readFrom (*_data->is, _data->version); - initialize(); + is = new StdIFStream (fileName); + readMagicNumberAndVersionField(*is, _data->version); + + // + // Backward compatibility to read multpart file. + // + if (isMultiPart(_data->version)) + { + compatibilityInitialize(*is); + return; + } + + _data->_streamData = new InputStreamMutex(); + _data->_streamData->is = is; + _data->header.readFrom (*_data->_streamData->is, _data->version); + initialize(); + //read tile offsets - we are not multipart or deep + _data->tileOffsets.readFrom (*(_data->_streamData->is), _data->fileIsComplete,false,false); + _data->_streamData->currentPosition = _data->_streamData->is->tellg(); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - delete _data; + if (_data->_streamData != 0) + { + if (_data->_streamData->is != 0) + { + delete _data->_streamData->is; + _data->_streamData->is = is = 0; + } - REPLACE_EXC (e, "Cannot open image file " - "\"" << fileName << "\". " << e); - throw; + delete _data->_streamData; + } + + if (is != 0) + delete is; + + REPLACE_EXC (e, "Cannot open image file " + "\"" << fileName << "\". " << e.what()); + throw; } catch (...) { - delete _data; + if ( _data->_streamData != 0) + { + if ( _data->_streamData->is != 0) + { + delete _data->_streamData->is; + _data->_streamData->is = is = 0; + } + + delete _data->_streamData; + } + + if (is != 0) + delete is; throw; } } -TiledInputFile::TiledInputFile (IStream &is, int numThreads): - _data (new Data (false, numThreads)) +TiledInputFile::TiledInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads): + _data (new Data (numThreads)) { + _data->_deleteStream=false; // // This constructor is called when a user // explicitly wants to read a tiled file. // + bool streamDataCreated = false; + try { - _data->is = &is; - _data->header.readFrom (*_data->is, _data->version); - initialize(); + readMagicNumberAndVersionField(is, _data->version); + + // + // Backward compatibility to read multpart file. + // + if (isMultiPart(_data->version)) + { + compatibilityInitialize(is); + return; + } + + streamDataCreated = true; + _data->_streamData = new InputStreamMutex(); + _data->_streamData->is = &is; + _data->header.readFrom (*_data->_streamData->is, _data->version); + initialize(); + // file is guaranteed to be single part, regular image + _data->tileOffsets.readFrom (*(_data->_streamData->is), _data->fileIsComplete,false,false); + _data->memoryMapped = _data->_streamData->is->isMemoryMapped(); + _data->_streamData->currentPosition = _data->_streamData->is->tellg(); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - delete _data; + if (streamDataCreated) delete _data->_streamData; + delete _data; - REPLACE_EXC (e, "Cannot open image file " - "\"" << is.fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Cannot open image file " + "\"" << is.fileName() << "\". " << e.what()); + throw; } catch (...) { - delete _data; + if (streamDataCreated) delete _data->_streamData; + delete _data; throw; } } -TiledInputFile::TiledInputFile - (const Header &header, - IStream *is, - int version, - int numThreads) -: - _data (new Data (false, numThreads)) +TiledInputFile::TiledInputFile (const Header &header, + OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, + int version, + int numThreads) : + _data (new Data (numThreads)) { + _data->_deleteStream=false; + _data->_streamData = new InputStreamMutex(); // // This constructor called by class Imf::InputFile // when a user wants to just read an image file, and // doesn't care or know if the file is tiled. + // No need to have backward compatibility here, because + // we have somehow got the header. // - _data->is = is; + _data->_streamData->is = is; _data->header = header; _data->version = version; initialize(); + _data->tileOffsets.readFrom (*(_data->_streamData->is),_data->fileIsComplete,false,false); + _data->memoryMapped = is->isMemoryMapped(); + _data->_streamData->currentPosition = _data->_streamData->is->tellg(); +} + + +TiledInputFile::TiledInputFile (InputPartData* part) +{ + _data = new Data (part->numThreads); + _data->_deleteStream=false; + multiPartInitialize(part); } void -TiledInputFile::initialize () +TiledInputFile::compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is) { - if (!isTiled (_data->version)) - throw Iex::ArgExc ("Expected a tiled file but the file is not tiled."); + is.seekg(0); + // + // Construct a MultiPartInputFile, initialize TiledInputFile + // with the part 0 data. + // (TODO) maybe change the third parameter of the constructor of MultiPartInputFile later. + // + _data->multiPartBackwardSupport = true; + _data->multiPartFile = new MultiPartInputFile(is, _data->numThreads); + InputPartData* part = _data->multiPartFile->getPart(0); + multiPartInitialize(part); +} + + +void +TiledInputFile::multiPartInitialize(InputPartData* part) +{ + if (part->header.type() != TILEDIMAGE) + throw IEX_NAMESPACE::ArgExc("Can't build a TiledInputFile from a type-mismatched part."); + + _data->_streamData = part->mutex; + _data->header = part->header; + _data->version = part->version; + _data->partNumber = part->partNumber; + _data->memoryMapped = _data->_streamData->is->isMemoryMapped(); + initialize(); + _data->tileOffsets.readFrom(part->chunkOffsets,_data->fileIsComplete); + _data->_streamData->currentPosition = _data->_streamData->is->tellg(); +} + + +void +TiledInputFile::initialize () +{ + // fix bad types in header (arises when a tool built against an older version of + // OpenEXR converts a scanline image to tiled) + // only applies when file is a single part, regular image, tiled file + // + if(!isMultiPart(_data->version) && + !isNonImage(_data->version) && + isTiled(_data->version) && + _data->header.hasType() ) + { + _data->header.setType(TILEDIMAGE); + } + + if (_data->partNumber == -1) + { + if (!isTiled (_data->version)) + throw IEX_NAMESPACE::ArgExc ("Expected a tiled file but the file is not tiled."); + + } + else + { + if(_data->header.hasType() && _data->header.type()!=TILEDIMAGE) + { + throw IEX_NAMESPACE::ArgExc ("TiledInputFile used for non-tiledimage part."); + } + } + _data->header.sanityCheck (true); _data->tileDesc = _data->header.tileDescription(); @@ -723,7 +920,7 @@ TiledInputFile::initialize () // // Save the dataWindow information // - + const Box2i &dataWindow = _data->header.dataWindow(); _data->minX = dataWindow.min.x; _data->maxX = dataWindow.max.x; @@ -735,10 +932,10 @@ TiledInputFile::initialize () // precalculateTileInfo (_data->tileDesc, - _data->minX, _data->maxX, - _data->minY, _data->maxY, - _data->numXTiles, _data->numYTiles, - _data->numXLevels, _data->numYLevels); + _data->minX, _data->maxX, + _data->minY, _data->maxY, + _data->numXTiles, _data->numYTiles, + _data->numXLevels, _data->numYLevels); _data->bytesPerPixel = calculateBytesPerPixel (_data->header); @@ -753,33 +950,35 @@ TiledInputFile::initialize () for (size_t i = 0; i < _data->tileBuffers.size(); i++) { _data->tileBuffers[i] = new TileBuffer (newTileCompressor - (_data->header.compression(), - _data->maxBytesPerTileLine, - _data->tileDesc.ySize, - _data->header)); + (_data->header.compression(), + _data->maxBytesPerTileLine, + _data->tileDesc.ySize, + _data->header)); - if (!_data->is->isMemoryMapped ()) + if (!_data->_streamData->is->isMemoryMapped ()) _data->tileBuffers[i]->buffer = new char [_data->tileBufferSize]; } _data->tileOffsets = TileOffsets (_data->tileDesc.mode, - _data->numXLevels, - _data->numYLevels, - _data->numXTiles, - _data->numYTiles); - - _data->tileOffsets.readFrom (*(_data->is), _data->fileIsComplete); - - _data->currentPosition = _data->is->tellg(); + _data->numXLevels, + _data->numYLevels, + _data->numXTiles, + _data->numYTiles); } TiledInputFile::~TiledInputFile () { - if (!_data->is->isMemoryMapped()) + if (!_data->memoryMapped) for (size_t i = 0; i < _data->tileBuffers.size(); i++) delete [] _data->tileBuffers[i]->buffer; + if (_data->_deleteStream) + delete _data->_streamData->is; + + if (_data->partNumber == -1) + delete _data->_streamData; + delete _data; } @@ -787,7 +986,7 @@ TiledInputFile::~TiledInputFile () const char * TiledInputFile::fileName () const { - return _data->is->fileName(); + return _data->_streamData->is->fileName(); } @@ -805,10 +1004,10 @@ TiledInputFile::version () const } -void +void TiledInputFile::setFrameBuffer (const FrameBuffer &frameBuffer) { - Lock lock (*_data); + Lock lock (*_data->_streamData); // // Set the frame buffer @@ -832,11 +1031,11 @@ TiledInputFile::setFrameBuffer (const FrameBuffer &frameBuffer) if (i.channel().xSampling != j.slice().xSampling || i.channel().ySampling != j.slice().ySampling) - THROW (Iex::ArgExc, "X and/or y subsampling factors " - "of \"" << i.name() << "\" channel " - "of input file \"" << fileName() << "\" are " - "not compatible with the frame buffer's " - "subsampling factors."); + THROW (IEX_NAMESPACE::ArgExc, "X and/or y subsampling factors " + "of \"" << i.name() << "\" channel " + "of input file \"" << fileName() << "\" are " + "not compatible with the frame buffer's " + "subsampling factors."); } // @@ -859,13 +1058,13 @@ TiledInputFile::setFrameBuffer (const FrameBuffer &frameBuffer) // slices.push_back (TInSliceInfo (i.channel().type, - i.channel().type, - 0, // base - 0, // xStride - 0, // yStride - false, // fill - true, // skip - 0.0)); // fillValue + i.channel().type, + 0, // base + 0, // xStride + 0, // yStride + false, // fill + true, // skip + 0.0)); // fillValue ++i; } @@ -898,21 +1097,21 @@ TiledInputFile::setFrameBuffer (const FrameBuffer &frameBuffer) while (i != channels.end()) { - // - // Channel i is present in the file but not - // in the frame buffer; data for channel i - // will be skipped during readPixels(). - // - - slices.push_back (TInSliceInfo (i.channel().type, - i.channel().type, - 0, // base - 0, // xStride - 0, // yStride - false, // fill - true, // skip - 0.0)); // fillValue - ++i; + // + // Channel i is present in the file but not + // in the frame buffer; data for channel i + // will be skipped during readPixels(). + // + + slices.push_back (TInSliceInfo (i.channel().type, + i.channel().type, + 0, // base + 0, // xStride + 0, // yStride + false, // fill + true, // skip + 0.0)); // fillValue + ++i; } // @@ -927,7 +1126,7 @@ TiledInputFile::setFrameBuffer (const FrameBuffer &frameBuffer) const FrameBuffer & TiledInputFile::frameBuffer () const { - Lock lock (*_data); + Lock lock (*_data->_streamData); return _data->frameBuffer; } @@ -948,27 +1147,33 @@ TiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly) try { - Lock lock (*_data); + Lock lock (*_data->_streamData); if (_data->slices.size() == 0) - throw Iex::ArgExc ("No frame buffer specified " - "as pixel data destination."); + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data destination."); + + if (!isValidLevel (lx, ly)) + THROW (IEX_NAMESPACE::ArgExc, + "Level coordinate " + "(" << lx << ", " << ly << ") " + "is invalid."); // // Determine the first and last tile coordinates in both dimensions. // We always attempt to read the range of tiles in the order that // they are stored in the file. // - + if (dx1 > dx2) std::swap (dx1, dx2); - + if (dy1 > dy2) std::swap (dy1, dy2); - + int dyStart = dy1; - int dyStop = dy2 + 1; - int dY = 1; + int dyStop = dy2 + 1; + int dY = 1; if (_data->lineOrder == DECREASING_Y) { @@ -979,24 +1184,25 @@ TiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly) // // Create a task group for all tile buffer tasks. When the - // task group goes out of scope, the destructor waits until - // all tasks are complete. + // task group goes out of scope, the destructor waits until + // all tasks are complete. // - + { TaskGroup taskGroup; int tileNumber = 0; - + for (int dy = dyStart; dy != dyStop; dy += dY) { for (int dx = dx1; dx <= dx2; dx++) { if (!isValidTile (dx, dy, lx, ly)) - THROW (Iex::ArgExc, - "Tile (" << dx << ", " << dy << ", " << - lx << "," << ly << ") is not a valid tile."); - + THROW (IEX_NAMESPACE::ArgExc, + "Tile (" << dx << ", " << dy << ", " << + lx << "," << ly << ") is not a valid tile."); + ThreadPool::addGlobalTask (newTileBufferTask (&taskGroup, + _data->_streamData, _data, tileNumber++, dx, dy, @@ -1004,65 +1210,65 @@ TiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly) } } - // + // // finish all tasks - // + // } - // - // Exeption handling: - // - // TileBufferTask::execute() may have encountered exceptions, but - // those exceptions occurred in another thread, not in the thread - // that is executing this call to TiledInputFile::readTiles(). - // TileBufferTask::execute() has caught all exceptions and stored - // the exceptions' what() strings in the tile buffers. - // Now we check if any tile buffer contains a stored exception; if - // this is the case then we re-throw the exception in this thread. - // (It is possible that multiple tile buffers contain stored - // exceptions. We re-throw the first exception we find and - // ignore all others.) - // - - const string *exception = 0; - - for (int i = 0; i < _data->tileBuffers.size(); ++i) - { + // + // Exeption handling: + // + // TileBufferTask::execute() may have encountered exceptions, but + // those exceptions occurred in another thread, not in the thread + // that is executing this call to TiledInputFile::readTiles(). + // TileBufferTask::execute() has caught all exceptions and stored + // the exceptions' what() strings in the tile buffers. + // Now we check if any tile buffer contains a stored exception; if + // this is the case then we re-throw the exception in this thread. + // (It is possible that multiple tile buffers contain stored + // exceptions. We re-throw the first exception we find and + // ignore all others.) + // + + const string *exception = 0; + + for (size_t i = 0; i < _data->tileBuffers.size(); ++i) + { TileBuffer *tileBuffer = _data->tileBuffers[i]; - if (tileBuffer->hasException && !exception) - exception = &tileBuffer->exception; + if (tileBuffer->hasException && !exception) + exception = &tileBuffer->exception; - tileBuffer->hasException = false; - } + tileBuffer->hasException = false; + } - if (exception) - throw Iex::IoExc (*exception); + if (exception) + throw IEX_NAMESPACE::IoExc (*exception); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { REPLACE_EXC (e, "Error reading pixel data from image " - "file \"" << fileName() << "\". " << e); + "file \"" << fileName() << "\". " << e.what()); throw; } } -void +void TiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int l) { readTiles (dx1, dx2, dy1, dy2, l, l); } -void +void TiledInputFile::readTile (int dx, int dy, int lx, int ly) { readTiles (dx, dx, dy, dy, lx, ly); } -void +void TiledInputFile::readTile (int dx, int dy, int l) { readTile (dx, dy, l, l); @@ -1071,30 +1277,48 @@ TiledInputFile::readTile (int dx, int dy, int l) void TiledInputFile::rawTileData (int &dx, int &dy, - int &lx, int &ly, + int &lx, int &ly, const char *&pixelData, - int &pixelDataSize) + int &pixelDataSize) { try { - Lock lock (*_data); + Lock lock (*_data->_streamData); if (!isValidTile (dx, dy, lx, ly)) - throw Iex::ArgExc ("Tried to read a tile outside " - "the image file's data window."); + throw IEX_NAMESPACE::ArgExc ("Tried to read a tile outside " + "the image file's data window."); TileBuffer *tileBuffer = _data->getTileBuffer (0); - readNextTileData (_data, dx, dy, lx, ly, - tileBuffer->buffer, + // + // if file is a multipart file, we have to seek to the required tile + // since we don't know where the file pointer is + // + int old_dx=dx; + int old_dy=dy; + int old_lx=lx; + int old_ly=ly; + if(isMultiPart(version())) + { + _data->_streamData->is->seekg(_data->tileOffsets(dx,dy,lx,ly)); + } + readNextTileData (_data->_streamData, _data, dx, dy, lx, ly, + tileBuffer->buffer, pixelDataSize); - + if(isMultiPart(version())) + { + if (old_dx!=dx || old_dy !=dy || old_lx!=lx || old_ly!=ly) + { + throw IEX_NAMESPACE::ArgExc ("rawTileData read the wrong tile"); + } + } pixelData = tileBuffer->buffer; } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { REPLACE_EXC (e, "Error reading pixel data from image " - "file \"" << fileName() << "\". " << e); + "file \"" << fileName() << "\". " << e.what()); throw; } } @@ -1132,10 +1356,10 @@ int TiledInputFile::numLevels () const { if (levelMode() == RIPMAP_LEVELS) - THROW (Iex::LogicExc, "Error calling numLevels() on image " - "file \"" << fileName() << "\" " - "(numLevels() is not defined for files " - "with RIPMAP level mode)."); + THROW (IEX_NAMESPACE::LogicExc, "Error calling numLevels() on image " + "file \"" << fileName() << "\" " + "(numLevels() is not defined for files " + "with RIPMAP level mode)."); return _data->numXLevels; } @@ -1155,17 +1379,17 @@ TiledInputFile::numYLevels () const } -bool +bool TiledInputFile::isValidLevel (int lx, int ly) const { if (lx < 0 || ly < 0) - return false; + return false; if (levelMode() == MIPMAP_LEVELS && lx != ly) - return false; + return false; if (lx >= numXLevels() || ly >= numYLevels()) - return false; + return false; return true; } @@ -1177,13 +1401,13 @@ TiledInputFile::levelWidth (int lx) const try { return levelSize (_data->minX, _data->maxX, lx, - _data->tileDesc.roundingMode); + _data->tileDesc.roundingMode); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error calling levelWidth() on image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error calling levelWidth() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -1196,11 +1420,11 @@ TiledInputFile::levelHeight (int ly) const return levelSize (_data->minY, _data->maxY, ly, _data->tileDesc.roundingMode); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error calling levelHeight() on image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error calling levelHeight() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -1210,12 +1434,12 @@ TiledInputFile::numXTiles (int lx) const { if (lx < 0 || lx >= _data->numXLevels) { - THROW (Iex::ArgExc, "Error calling numXTiles() on image " - "file \"" << _data->is->fileName() << "\" " - "(Argument is not in valid range)."); + THROW (IEX_NAMESPACE::ArgExc, "Error calling numXTiles() on image " + "file \"" << _data->_streamData->is->fileName() << "\" " + "(Argument is not in valid range)."); } - + return _data->numXTiles[lx]; } @@ -1225,11 +1449,11 @@ TiledInputFile::numYTiles (int ly) const { if (ly < 0 || ly >= _data->numYLevels) { - THROW (Iex::ArgExc, "Error calling numYTiles() on image " - "file \"" << _data->is->fileName() << "\" " - "(Argument is not in valid range)."); + THROW (IEX_NAMESPACE::ArgExc, "Error calling numYTiles() on image " + "file \"" << _data->_streamData->is->fileName() << "\" " + "(Argument is not in valid range)."); } - + return _data->numYTiles[ly]; } @@ -1246,16 +1470,17 @@ TiledInputFile::dataWindowForLevel (int lx, int ly) const { try { - return Imf::dataWindowForLevel (_data->tileDesc, - _data->minX, _data->maxX, - _data->minY, _data->maxY, - lx, ly); + return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForLevel ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + lx, ly); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error calling dataWindowForLevel() on image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error calling dataWindowForLevel() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -1272,19 +1497,20 @@ TiledInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const { try { - if (!isValidTile (dx, dy, lx, ly)) - throw Iex::ArgExc ("Arguments not in valid range."); - - return Imf::dataWindowForTile (_data->tileDesc, - _data->minX, _data->maxX, - _data->minY, _data->maxY, - dx, dy, lx, ly); + if (!isValidTile (dx, dy, lx, ly)) + throw IEX_NAMESPACE::ArgExc ("Arguments not in valid range."); + + return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + dx, dy, lx, ly); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error calling dataWindowForTile() on image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error calling dataWindowForTile() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -1298,5 +1524,10 @@ TiledInputFile::isValidTile (int dx, int dy, int lx, int ly) const (dy < _data->numYTiles[ly] && dy >= 0)); } +void TiledInputFile::tileOrder(int dx[], int dy[], int lx[], int ly[]) const +{ + return _data->tileOffsets.getTileOrder(dx,dy,lx,ly); +} + -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTiledInputFile.h b/3rdparty/openexr/IlmImf/ImfTiledInputFile.h index eac9968727..5ea872d3cf 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledInputFile.h +++ b/3rdparty/openexr/IlmImf/ImfTiledInputFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,22 +42,26 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" #include "ImathBox.h" -#include -#include +#include "ImfTileDescription.h" +#include "ImfThreading.h" +#include "ImfGenericInputFile.h" +#include "ImfTiledOutputFile.h" +#include "ImfNamespace.h" +#include "ImfExport.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -class TiledInputFile +class TiledInputFile : public GenericInputFile { public: //-------------------------------------------------------------------- // A constructor that opens the file with the specified name, and - // reads the file header. The constructor throws an Iex::ArgExc + // reads the file header. The constructor throws an IEX_NAMESPACE::ArgExc // exception if the file is not tiled. // The numThreads parameter specifies how many worker threads this // file will try to keep busy when decompressing individual tiles. @@ -65,25 +69,28 @@ class TiledInputFile // automatically closes the corresponding files. //-------------------------------------------------------------------- + IMF_EXPORT TiledInputFile (const char fileName[], int numThreads = globalThreadCount ()); - + // ---------------------------------------------------------- // A constructor that attaches the new TiledInputFile object - // to a file that has already been opened. + // to a file that has already been opened. // Destroying TiledInputFile objects constructed with this // constructor does not automatically close the corresponding // files. // ---------------------------------------------------------- - TiledInputFile (IStream &is, int numThreads = globalThreadCount ()); + IMF_EXPORT + TiledInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount ()); //----------- // Destructor //----------- + IMF_EXPORT virtual ~TiledInputFile (); @@ -91,6 +98,7 @@ class TiledInputFile // Access to the file name //------------------------ + IMF_EXPORT const char * fileName () const; @@ -98,6 +106,7 @@ class TiledInputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; @@ -105,6 +114,7 @@ class TiledInputFile // Access to the file format version //---------------------------------- + IMF_EXPORT int version () const; @@ -119,6 +129,7 @@ class TiledInputFile // to readTile(). //----------------------------------------------------------- + IMF_EXPORT void setFrameBuffer (const FrameBuffer &frameBuffer); @@ -126,6 +137,7 @@ class TiledInputFile // Access to the current frame buffer //----------------------------------- + IMF_EXPORT const FrameBuffer & frameBuffer () const; @@ -139,6 +151,7 @@ class TiledInputFile // prematurely.) //------------------------------------------------------------ + IMF_EXPORT bool isComplete () const; @@ -152,9 +165,13 @@ class TiledInputFile // fields of the file header's TileDescriptionAttribute. //--------------------------------------------------------- + IMF_EXPORT unsigned int tileXSize () const; + IMF_EXPORT unsigned int tileYSize () const; + IMF_EXPORT LevelMode levelMode () const; + IMF_EXPORT LevelRoundingMode levelRoundingMode () const; @@ -194,16 +211,20 @@ class TiledInputFile // return value is the same as for numXLevels() // // if levelMode() == RIPMAP_LEVELS: - // an Iex::LogicExc exception is thrown + // an IEX_NAMESPACE::LogicExc exception is thrown // - // isValidLevel(lx, ly) returns true if the file contains + // isValidLevel(lx, ly) returns true if the file contains // a level with level number (lx, ly), false if not. // //-------------------------------------------------------------------- + IMF_EXPORT int numLevels () const; + IMF_EXPORT int numXLevels () const; + IMF_EXPORT int numYLevels () const; + IMF_EXPORT bool isValidLevel (int lx, int ly) const; @@ -225,7 +246,9 @@ class TiledInputFile // //---------------------------------------------------------- + IMF_EXPORT int levelWidth (int lx) const; + IMF_EXPORT int levelHeight (int ly) const; @@ -249,7 +272,9 @@ class TiledInputFile // //-------------------------------------------------------------- + IMF_EXPORT int numXTiles (int lx = 0) const; + IMF_EXPORT int numYTiles (int ly = 0) const; @@ -272,8 +297,10 @@ class TiledInputFile // //--------------------------------------------------------------- - Imath::Box2i dataWindowForLevel (int l = 0) const; - Imath::Box2i dataWindowForLevel (int lx, int ly) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; //------------------------------------------------------------------- @@ -297,9 +324,11 @@ class TiledInputFile // //------------------------------------------------------------------- - Imath::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; - Imath::Box2i dataWindowForTile (int dx, int dy, + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int lx, int ly) const; //------------------------------------------------------------ @@ -331,12 +360,16 @@ class TiledInputFile // //------------------------------------------------------------ + IMF_EXPORT void readTile (int dx, int dy, int l = 0); + IMF_EXPORT void readTile (int dx, int dy, int lx, int ly); + IMF_EXPORT void readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly); + IMF_EXPORT void readTiles (int dx1, int dx2, int dy1, int dy2, int l = 0); @@ -345,37 +378,54 @@ class TiledInputFile // Read a tile of raw pixel data from the file, // without uncompressing it (this function is // used to implement TiledOutputFile::copyPixels()). + // + // for single part files, reads the next tile in the file + // for multipart files, reads the tile specified by dx,dy,lx,ly + // //-------------------------------------------------- + IMF_EXPORT void rawTileData (int &dx, int &dy, - int &lx, int &ly, - const char *&pixelData, - int &pixelDataSize); + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize); struct Data; private: friend class InputFile; + friend class MultiPartInputFile; + + TiledInputFile (InputPartData* part); TiledInputFile (const TiledInputFile &); // not implemented TiledInputFile & operator = (const TiledInputFile &); // not implemented - TiledInputFile (const Header &header, IStream *is, int version, + TiledInputFile (const Header &header, OPENEXR_IMF_INTERNAL_NAMESPACE::IStream *is, int version, int numThreads); void initialize (); + void multiPartInitialize(InputPartData* part); + void compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is); bool isValidTile (int dx, int dy, - int lx, int ly) const; + int lx, int ly) const; size_t bytesPerLineForTile (int dx, int dy, - int lx, int ly) const; + int lx, int ly) const; + void tileOrder(int dx[],int dy[],int lx[],int ly[]) const; Data * _data; + + friend void TiledOutputFile::copyPixels(TiledInputFile &); }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfTiledInputPart.cpp b/3rdparty/openexr/IlmImf/ImfTiledInputPart.cpp new file mode 100644 index 0000000000..3f89d95dc4 --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfTiledInputPart.cpp @@ -0,0 +1,208 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfTiledInputPart.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +TiledInputPart::TiledInputPart(MultiPartInputFile& multiPartFile, int partNumber) +{ + file = multiPartFile.getInputPart(partNumber); +} + +const char * +TiledInputPart::fileName () const +{ + return file->fileName(); +} + +const Header & +TiledInputPart::header () const +{ + return file->header(); +} + +int +TiledInputPart::version () const +{ + return file->version(); +} + +void +TiledInputPart::setFrameBuffer (const FrameBuffer &frameBuffer) +{ + file->setFrameBuffer(frameBuffer); +} + +const FrameBuffer & +TiledInputPart::frameBuffer () const +{ + return file->frameBuffer(); +} + +bool +TiledInputPart::isComplete () const +{ + return file->isComplete(); +} + +unsigned int +TiledInputPart::tileXSize () const +{ + return file->tileXSize(); +} + +unsigned int +TiledInputPart::tileYSize () const +{ + return file->tileYSize(); +} + +LevelMode +TiledInputPart::levelMode () const +{ + return file->levelMode(); +} + +LevelRoundingMode +TiledInputPart::levelRoundingMode () const +{ + return file->levelRoundingMode(); +} + +int +TiledInputPart::numLevels () const +{ + return file->numLevels(); +} + +int +TiledInputPart::numXLevels () const +{ + return file->numXLevels(); +} + +int +TiledInputPart::numYLevels () const +{ + return file->numYLevels(); +} + +bool +TiledInputPart::isValidLevel (int lx, int ly) const +{ + return file->isValidLevel(lx, ly); +} + +int +TiledInputPart::levelWidth (int lx) const +{ + return file->levelWidth(lx); +} + +int +TiledInputPart::levelHeight (int ly) const +{ + return file->levelHeight(ly); +} + +int +TiledInputPart::numXTiles (int lx) const +{ + return file->numXTiles(lx); +} + +int +TiledInputPart::numYTiles (int ly) const +{ + return file->numYTiles(ly); +} + +IMATH_NAMESPACE::Box2i +TiledInputPart::dataWindowForLevel (int l) const +{ + return file->dataWindowForLevel(l); +} + +IMATH_NAMESPACE::Box2i +TiledInputPart::dataWindowForLevel (int lx, int ly) const +{ + return file->dataWindowForLevel(lx, ly); +} + +IMATH_NAMESPACE::Box2i +TiledInputPart::dataWindowForTile (int dx, int dy, int l) const +{ + return file->dataWindowForTile(dx, dy, l); +} + +IMATH_NAMESPACE::Box2i +TiledInputPart::dataWindowForTile (int dx, int dy, int lx, int ly) const +{ + return file->dataWindowForTile(dx, dy, lx, ly); +} + +void +TiledInputPart::readTile (int dx, int dy, int l) +{ + file->readTile(dx, dy, l); +} + +void +TiledInputPart::readTile (int dx, int dy, int lx, int ly) +{ + file->readTile(dx, dy, lx, ly); +} + +void +TiledInputPart::readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly) +{ + file->readTiles(dx1, dx2, dy1, dy2, lx, ly); +} + +void +TiledInputPart::readTiles (int dx1, int dx2, int dy1, int dy2, int l) +{ + file->readTiles(dx1, dx2, dy1, dy2, l); +} + +void +TiledInputPart::rawTileData (int &dx, int &dy, int &lx, int &ly, + const char *&pixelData, int &pixelDataSize) +{ + file->rawTileData(dx, dy, lx, ly, pixelData, pixelDataSize); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTiledInputPart.h b/3rdparty/openexr/IlmImf/ImfTiledInputPart.h new file mode 100644 index 0000000000..4132ab8cec --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfTiledInputPart.h @@ -0,0 +1,128 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFTILEDINPUTPART_H_ +#define IMFTILEDINPUTPART_H_ + +#include "ImfMultiPartInputFile.h" +#include "ImfTiledInputFile.h" +#include "ImfNamespace.h" +#include "ImfForward.h" +#include "ImfExport.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//----------------------------------------------------------------------------- +// class TiledInputPart: +// +// Same interface as TiledInputFile. Please have a reference to TiledInputFile. +//----------------------------------------------------------------------------- + +class TiledInputPart +{ + public: + IMF_EXPORT + TiledInputPart(MultiPartInputFile& multiPartFile, int partNumber); + + IMF_EXPORT + const char * fileName () const; + IMF_EXPORT + const Header & header () const; + IMF_EXPORT + int version () const; + IMF_EXPORT + void setFrameBuffer (const FrameBuffer &frameBuffer); + IMF_EXPORT + const FrameBuffer & frameBuffer () const; + IMF_EXPORT + bool isComplete () const; + IMF_EXPORT + unsigned int tileXSize () const; + IMF_EXPORT + unsigned int tileYSize () const; + IMF_EXPORT + LevelMode levelMode () const; + IMF_EXPORT + LevelRoundingMode levelRoundingMode () const; + IMF_EXPORT + int numLevels () const; + IMF_EXPORT + int numXLevels () const; + IMF_EXPORT + int numYLevels () const; + IMF_EXPORT + bool isValidLevel (int lx, int ly) const; + IMF_EXPORT + int levelWidth (int lx) const; + IMF_EXPORT + int levelHeight (int ly) const; + IMF_EXPORT + int numXTiles (int lx = 0) const; + IMF_EXPORT + int numYTiles (int ly = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + IMF_EXPORT + void readTile (int dx, int dy, int l = 0); + IMF_EXPORT + void readTile (int dx, int dy, int lx, int ly); + IMF_EXPORT + void readTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + IMF_EXPORT + void readTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + IMF_EXPORT + void rawTileData (int &dx, int &dy, + int &lx, int &ly, + const char *&pixelData, + int &pixelDataSize); + + private: + TiledInputFile* file; + // for internal use - allow TiledOutputFile access to file for copyPixels + friend class TiledOutputFile; + +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFTILEDINPUTPART_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp b/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp index 9588e789f6..d72d823ad7 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp +++ b/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,27 +43,29 @@ #include "Iex.h" #include #include -#include // for std::max() +#include +#include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER -using Imath::Box2i; -using Imath::V2i; +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::V2i; int levelSize (int min, int max, int l, LevelRoundingMode rmode) { if (l < 0) - throw Iex::ArgExc ("Argument not in valid range."); + throw IEX_NAMESPACE::ArgExc ("Argument not in valid range."); int a = max - min + 1; int b = (1 << l); int size = a / b; if (rmode == ROUND_UP && size * b < a) - size += 1; + size += 1; return std::max (size, 1); } @@ -71,15 +73,15 @@ levelSize (int min, int max, int l, LevelRoundingMode rmode) Box2i dataWindowForLevel (const TileDescription &tileDesc, - int minX, int maxX, - int minY, int maxY, - int lx, int ly) + int minX, int maxX, + int minY, int maxY, + int lx, int ly) { V2i levelMin = V2i (minX, minY); V2i levelMax = levelMin + - V2i (levelSize (minX, maxX, lx, tileDesc.roundingMode) - 1, - levelSize (minY, maxY, ly, tileDesc.roundingMode) - 1); + V2i (levelSize (minX, maxX, lx, tileDesc.roundingMode) - 1, + levelSize (minY, maxY, ly, tileDesc.roundingMode) - 1); return Box2i(levelMin, levelMax); } @@ -87,21 +89,21 @@ dataWindowForLevel (const TileDescription &tileDesc, Box2i dataWindowForTile (const TileDescription &tileDesc, - int minX, int maxX, - int minY, int maxY, - int dx, int dy, - int lx, int ly) + int minX, int maxX, + int minY, int maxY, + int dx, int dy, + int lx, int ly) { V2i tileMin = V2i (minX + dx * tileDesc.xSize, - minY + dy * tileDesc.ySize); + minY + dy * tileDesc.ySize); V2i tileMax = tileMin + V2i (tileDesc.xSize - 1, tileDesc.ySize - 1); V2i levelMax = dataWindowForLevel - (tileDesc, minX, maxX, minY, maxY, lx, ly).max; + (tileDesc, minX, maxX, minY, maxY, lx, ly).max; tileMax = V2i (std::min (tileMax[0], levelMax[0]), - std::min (tileMax[1], levelMax[1])); + std::min (tileMax[1], levelMax[1])); return Box2i (tileMin, tileMax); } @@ -115,16 +117,50 @@ calculateBytesPerPixel (const Header &header) size_t bytesPerPixel = 0; for (ChannelList::ConstIterator c = channels.begin(); - c != channels.end(); - ++c) + c != channels.end(); + ++c) { - bytesPerPixel += pixelTypeSize (c.channel().type); + bytesPerPixel += pixelTypeSize (c.channel().type); } return bytesPerPixel; } +void +calculateBytesPerLine (const Header &header, + char* sampleCountBase, + int sampleCountXStride, + int sampleCountYStride, + int minX, int maxX, + int minY, int maxY, + std::vector& xOffsets, + std::vector& yOffsets, + std::vector& bytesPerLine) +{ + const ChannelList &channels = header.channels(); + + int pos = 0; + for (ChannelList::ConstIterator c = channels.begin(); + c != channels.end(); + ++c, ++pos) + { + int xOffset = xOffsets[pos]; + int yOffset = yOffsets[pos]; + int i = 0; + for (int y = minY - yOffset; y <= maxY - yOffset; y++, i++) + for (int x = minX - xOffset; x <= maxX - xOffset; x++) + { + bytesPerLine[i] += sampleCount(sampleCountBase, + sampleCountXStride, + sampleCountYStride, + x, y) + * pixelTypeSize (c.channel().type); + } + } +} + + namespace { int @@ -138,8 +174,8 @@ floorLog2 (int x) while (x > 1) { - y += 1; - x >>= 1; + y += 1; + x >>= 1; } return y; @@ -158,11 +194,11 @@ ceilLog2 (int x) while (x > 1) { - if (x & 1) - r = 1; + if (x & 1) + r = 1; - y += 1; - x >>= 1; + y += 1; + x >>= 1; } return y + r; @@ -178,8 +214,8 @@ roundLog2 (int x, LevelRoundingMode rmode) int calculateNumXLevels (const TileDescription& tileDesc, - int minX, int maxX, - int minY, int maxY) + int minX, int maxX, + int minY, int maxY) { int num = 0; @@ -187,29 +223,29 @@ calculateNumXLevels (const TileDescription& tileDesc, { case ONE_LEVEL: - num = 1; - break; + num = 1; + break; case MIPMAP_LEVELS: - { - int w = maxX - minX + 1; - int h = maxY - minY + 1; - num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1; - } + { + int w = maxX - minX + 1; + int h = maxY - minY + 1; + num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1; + } break; case RIPMAP_LEVELS: - { - int w = maxX - minX + 1; - num = roundLog2 (w, tileDesc.roundingMode) + 1; - } - break; + { + int w = maxX - minX + 1; + num = roundLog2 (w, tileDesc.roundingMode) + 1; + } + break; default: - throw Iex::ArgExc ("Unknown LevelMode format."); + throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format."); } return num; @@ -218,8 +254,8 @@ calculateNumXLevels (const TileDescription& tileDesc, int calculateNumYLevels (const TileDescription& tileDesc, - int minX, int maxX, - int minY, int maxY) + int minX, int maxX, + int minY, int maxY) { int num = 0; @@ -227,29 +263,29 @@ calculateNumYLevels (const TileDescription& tileDesc, { case ONE_LEVEL: - num = 1; - break; + num = 1; + break; case MIPMAP_LEVELS: - { - int w = maxX - minX + 1; - int h = maxY - minY + 1; - num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1; - } + { + int w = maxX - minX + 1; + int h = maxY - minY + 1; + num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1; + } break; case RIPMAP_LEVELS: - { - int h = maxY - minY + 1; - num = roundLog2 (h, tileDesc.roundingMode) + 1; - } - break; + { + int h = maxY - minY + 1; + num = roundLog2 (h, tileDesc.roundingMode) + 1; + } + break; default: - throw Iex::ArgExc ("Unknown LevelMode format."); + throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format."); } return num; @@ -258,14 +294,14 @@ calculateNumYLevels (const TileDescription& tileDesc, void calculateNumTiles (int *numTiles, - int numLevels, - int min, int max, - int size, - LevelRoundingMode rmode) + int numLevels, + int min, int max, + int size, + LevelRoundingMode rmode) { for (int i = 0; i < numLevels; i++) { - numTiles[i] = (levelSize (min, max, i, rmode) + size - 1) / size; + numTiles[i] = (levelSize (min, max, i, rmode) + size - 1) / size; } } @@ -274,29 +310,80 @@ calculateNumTiles (int *numTiles, void precalculateTileInfo (const TileDescription& tileDesc, - int minX, int maxX, - int minY, int maxY, - int *&numXTiles, int *&numYTiles, - int &numXLevels, int &numYLevels) + int minX, int maxX, + int minY, int maxY, + int *&numXTiles, int *&numYTiles, + int &numXLevels, int &numYLevels) { numXLevels = calculateNumXLevels(tileDesc, minX, maxX, minY, maxY); numYLevels = calculateNumYLevels(tileDesc, minX, maxX, minY, maxY); - + numXTiles = new int[numXLevels]; numYTiles = new int[numYLevels]; calculateNumTiles (numXTiles, - numXLevels, - minX, maxX, - tileDesc.xSize, - tileDesc.roundingMode); + numXLevels, + minX, maxX, + tileDesc.xSize, + tileDesc.roundingMode); calculateNumTiles (numYTiles, - numYLevels, - minY, maxY, - tileDesc.ySize, - tileDesc.roundingMode); + numYLevels, + minY, maxY, + tileDesc.ySize, + tileDesc.roundingMode); +} + + +int +getTiledChunkOffsetTableSize(const Header& header) +{ + // + // Save the dataWindow information + // + + const Box2i &dataWindow = header.dataWindow(); + + // + // Precompute level and tile information. + // + + int* numXTiles; + int* numYTiles; + int numXLevels; + int numYLevels; + precalculateTileInfo (header.tileDescription(), + dataWindow.min.x, dataWindow.max.x, + dataWindow.min.y, dataWindow.max.y, + numXTiles, numYTiles, + numXLevels, numYLevels); + + // + // Calculate lineOffsetSize. + // + int lineOffsetSize = 0; + const TileDescription &desc = header.tileDescription(); + switch (desc.mode) + { + case ONE_LEVEL: + case MIPMAP_LEVELS: + for (int i = 0; i < numXLevels; i++) + lineOffsetSize += numXTiles[i] * numYTiles[i]; + break; + case RIPMAP_LEVELS: + for (int i = 0; i < numXLevels; i++) + for (int j = 0; j < numYLevels; j++) + lineOffsetSize += numXTiles[i] * numYTiles[j]; + break; + case NUM_LEVELMODES : + throw IEX_NAMESPACE::LogicExc("Bad level mode getting chunk offset table size"); + } + + delete[] numXTiles; + delete[] numYTiles; + + return lineOffsetSize; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTiledMisc.h b/3rdparty/openexr/IlmImf/ImfTiledMisc.h index 7a83f1e486..2696663651 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledMisc.h +++ b/3rdparty/openexr/IlmImf/ImfTiledMisc.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,33 +43,64 @@ //----------------------------------------------------------------------------- #include "ImathBox.h" -#include +#include "ImfHeader.h" +#include "ImfNamespace.h" + #include +#include + -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER +IMF_EXPORT int levelSize (int min, int max, int l, LevelRoundingMode rmode); -Imath::Box2i dataWindowForLevel (const TileDescription &tileDesc, - int minX, int maxX, - int minY, int maxY, - int lx, int ly); +IMF_EXPORT +IMATH_NAMESPACE::Box2i dataWindowForLevel (const TileDescription &tileDesc, + int minX, int maxX, + int minY, int maxY, + int lx, int ly); -Imath::Box2i dataWindowForTile (const TileDescription &tileDesc, - int minX, int maxX, - int minY, int maxY, - int dx, int dy, - int lx, int ly); +IMF_EXPORT +IMATH_NAMESPACE::Box2i dataWindowForTile (const TileDescription &tileDesc, + int minX, int maxX, + int minY, int maxY, + int dx, int dy, + int lx, int ly); +IMF_EXPORT size_t calculateBytesPerPixel (const Header &header); +// +// Calculate the count of bytes for each lines in range [minY, maxY], +// and pixels in range [minX, maxX]. +// Data will be saved in bytesPerLine. +// sampleCountBase, sampleCountXStride and sampleCountYStride are +// used to get the sample count values. +// + +IMF_EXPORT +void calculateBytesPerLine (const Header &header, + char* sampleCountBase, + int sampleCountXStride, + int sampleCountYStride, + int minX, int maxX, + int minY, int maxY, + std::vector& xOffsets, + std::vector& yOffsets, + std::vector& bytesPerLine); + +IMF_EXPORT void precalculateTileInfo (const TileDescription& tileDesc, - int minX, int maxX, - int minY, int maxY, - int *&numXTiles, int *&numYTiles, - int &numXLevels, int &numYLevels); + int minX, int maxX, + int minY, int maxY, + int *&numXTiles, int *&numYTiles, + int &numXLevels, int &numYLevels); + +IMF_EXPORT +int getTiledChunkOffsetTableSize(const Header& header); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp index 0bc3cb3c30..b9572d0bc2 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -40,7 +40,9 @@ #include #include +#include #include +#include #include #include #include @@ -54,22 +56,27 @@ #include #include #include +#include #include "IlmThreadPool.h" #include "IlmThreadSemaphore.h" #include "IlmThreadMutex.h" +#include "ImfOutputStreamMutex.h" +#include "ImfOutputPartData.h" #include "Iex.h" #include #include #include #include #include -#include // for std::max() +#include +#include "ImfNamespace.h" -namespace Imf { -using Imath::Box2i; -using Imath::V2i; +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +using IMATH_NAMESPACE::Box2i; +using IMATH_NAMESPACE::V2i; using std::string; using std::vector; using std::ofstream; @@ -77,12 +84,12 @@ using std::map; using std::min; using std::max; using std::swap; -using IlmThread::Mutex; -using IlmThread::Lock; -using IlmThread::Semaphore; -using IlmThread::Task; -using IlmThread::TaskGroup; -using IlmThread::ThreadPool; +using ILMTHREAD_NAMESPACE::Mutex; +using ILMTHREAD_NAMESPACE::Lock; +using ILMTHREAD_NAMESPACE::Semaphore; +using ILMTHREAD_NAMESPACE::Task; +using ILMTHREAD_NAMESPACE::TaskGroup; +using ILMTHREAD_NAMESPACE::ThreadPool; namespace { @@ -97,19 +104,19 @@ struct TOutSliceInfo int yTileCoords; TOutSliceInfo (PixelType type = HALF, - const char *base = 0, - size_t xStride = 0, - size_t yStride = 0, - bool zero = false, + const char *base = 0, + size_t xStride = 0, + size_t yStride = 0, + bool zero = false, int xTileCoords = 0, int yTileCoords = 0); }; TOutSliceInfo::TOutSliceInfo (PixelType t, - const char *b, - size_t xs, size_t ys, - bool z, + const char *b, + size_t xs, size_t ys, + bool z, int xtc, int ytc) : @@ -131,25 +138,25 @@ struct TileCoord int dy; int lx; int ly; - + TileCoord (int xTile = 0, int yTile = 0, - int xLevel = 0, int yLevel = 0) + int xLevel = 0, int yLevel = 0) : dx (xTile), dy (yTile), - lx (xLevel), ly (yLevel) + lx (xLevel), ly (yLevel) { // empty } - + bool operator < (const TileCoord &other) const { return (ly < other.ly) || - (ly == other.ly && lx < other.lx) || - ((ly == other.ly && lx == other.lx) && - ((dy < other.dy) || (dy == other.dy && dx < other.dx))); + (ly == other.ly && lx < other.lx) || + ((ly == other.ly && lx == other.lx) && + ((dy < other.dy) || (dy == other.dy && dx < other.dx))); } @@ -157,9 +164,9 @@ struct TileCoord operator == (const TileCoord &other) const { return lx == other.lx && - ly == other.ly && - dx == other.dx && - dy == other.dy; + ly == other.ly && + dx == other.dx && + dy == other.dy; } }; @@ -170,16 +177,16 @@ struct BufferedTile int pixelDataSize; BufferedTile (const char *data, int size): - pixelData (0), - pixelDataSize(size) + pixelData (0), + pixelDataSize(size) { - pixelData = new char[pixelDataSize]; - memcpy (pixelData, data, pixelDataSize); + pixelData = new char[pixelDataSize]; + memcpy (pixelData, data, pixelDataSize); } ~BufferedTile() { - delete [] pixelData; + delete [] pixelData; } }; @@ -230,10 +237,11 @@ TileBuffer::~TileBuffer () } // namespace -struct TiledOutputFile::Data: public Mutex +struct TiledOutputFile::Data { Header header; // the image header int version; // file format version + bool multipart; // part came from a multipart file TileDescription tileDesc; // describes the tile layout FrameBuffer frameBuffer; // framebuffer to write into Int64 previewPosition; @@ -249,44 +257,43 @@ struct TiledOutputFile::Data: public Mutex int * numYTiles; // number of y tiles at a level TileOffsets tileOffsets; // stores offsets in file for - // each tile + // each tile Compressor::Format format; // compressor's data format vector slices; // info about channels in file - OStream * os; // file stream to write to - bool deleteStream; size_t maxBytesPerTileLine; // combined size of a tile line - // over all channels - + // over all channels + vector tileBuffers; size_t tileBufferSize; // size of a tile buffer Int64 tileOffsetsPosition; // position of the tile index - Int64 currentPosition; // current position in the file - + TileMap tileMap; TileCoord nextTileToWrite; - Data (bool del, int numThreads); - ~Data (); + int partNumber; // the output part number + Data (int numThreads); + ~Data (); + inline TileBuffer * getTileBuffer (int number); - // hash function from tile - // buffer coords into our - // vector of tile buffers - + // hash function from tile + // buffer coords into our + // vector of tile buffers + TileCoord nextTileCoord (const TileCoord &a); }; -TiledOutputFile::Data::Data (bool del, int numThreads): +TiledOutputFile::Data::Data (int numThreads): + multipart(false), numXTiles(0), numYTiles(0), - os (0), - deleteStream (del), - tileOffsetsPosition (0) + tileOffsetsPosition (0), + partNumber(-1) { // // We need at least one tileBuffer, but if threading is used, @@ -302,15 +309,12 @@ TiledOutputFile::Data::~Data () delete [] numXTiles; delete [] numYTiles; - if (deleteStream) - delete os; - // // Delete all the tile buffers, if any still happen to exist // - + for (TileMap::iterator i = tileMap.begin(); i != tileMap.end(); ++i) - delete i->second; + delete i->second; for (size_t i = 0; i < tileBuffers.size(); i++) delete tileBuffers[i]; @@ -328,7 +332,7 @@ TileCoord TiledOutputFile::Data::nextTileCoord (const TileCoord &a) { TileCoord b = a; - + if (lineOrder == INCREASING_Y) { b.dx++; @@ -340,9 +344,9 @@ TiledOutputFile::Data::nextTileCoord (const TileCoord &a) if (b.dy >= numYTiles[b.ly]) { - // - // the next tile is in the next level - // + // + // the next tile is in the next level + // b.dy = 0; @@ -364,11 +368,14 @@ TiledOutputFile::Data::nextTileCoord (const TileCoord &a) b.lx = 0; b.ly++; - #ifdef DEBUG - assert (b.ly <= numYLevels); - #endif + #ifdef DEBUG + assert (b.ly <= numYLevels); + #endif } break; + case NUM_LEVELMODES: + throw(IEX_NAMESPACE::ArgExc("Invalid tile description")); + } } } @@ -384,9 +391,9 @@ TiledOutputFile::Data::nextTileCoord (const TileCoord &a) if (b.dy < 0) { - // - // the next tile is in the next level - // + // + // the next tile is in the next level + // switch (tileDesc.mode) { @@ -406,29 +413,33 @@ TiledOutputFile::Data::nextTileCoord (const TileCoord &a) b.lx = 0; b.ly++; - #ifdef DEBUG - assert (b.ly <= numYLevels); - #endif + #ifdef DEBUG + assert (b.ly <= numYLevels); + #endif } break; + case NUM_LEVELMODES: + throw(IEX_NAMESPACE::ArgExc("Invalid tile description")); + } - if (b.ly < numYLevels) - b.dy = numYTiles[b.ly] - 1; + if (b.ly < numYLevels) + b.dy = numYTiles[b.ly] - 1; } } } - - return b; + + return b; } namespace { void -writeTileData (TiledOutputFile::Data *ofd, +writeTileData (OutputStreamMutex *streamData, + TiledOutputFile::Data *ofd, int dx, int dy, - int lx, int ly, + int lx, int ly, const char pixelData[], int pixelDataSize) { @@ -438,46 +449,56 @@ writeTileData (TiledOutputFile::Data *ofd, // without calling tellp() (tellp() can be fairly expensive). // - Int64 currentPosition = ofd->currentPosition; - ofd->currentPosition = 0; + Int64 currentPosition = streamData->currentPosition; + streamData->currentPosition = 0; if (currentPosition == 0) - currentPosition = ofd->os->tellp(); + currentPosition = streamData->os->tellp(); ofd->tileOffsets (dx, dy, lx, ly) = currentPosition; #ifdef DEBUG - assert (ofd->os->tellp() == currentPosition); + assert (streamData->os->tellp() == currentPosition); #endif // // Write the tile header. // - Xdr::write (*ofd->os, dx); - Xdr::write (*ofd->os, dy); - Xdr::write (*ofd->os, lx); - Xdr::write (*ofd->os, ly); - Xdr::write (*ofd->os, pixelDataSize); + if (ofd->multipart) + { + Xdr::write (*streamData->os, ofd->partNumber); + } + Xdr::write (*streamData->os, dx); + Xdr::write (*streamData->os, dy); + Xdr::write (*streamData->os, lx); + Xdr::write (*streamData->os, ly); + Xdr::write (*streamData->os, pixelDataSize); - ofd->os->write (pixelData, pixelDataSize); + streamData->os->write (pixelData, pixelDataSize); // - // Keep current position in the file so that we can avoid + // Keep current position in the file so that we can avoid // redundant seekg() operations (seekg() can be fairly expensive). // - ofd->currentPosition = currentPosition + + streamData->currentPosition = currentPosition + 5 * Xdr::size() + pixelDataSize; + + if (ofd->multipart) + { + streamData->currentPosition += Xdr::size(); + } } void -bufferedTileWrite (TiledOutputFile::Data *ofd, +bufferedTileWrite (OutputStreamMutex *streamData, + TiledOutputFile::Data *ofd, int dx, int dy, - int lx, int ly, + int lx, int ly, const char pixelData[], int pixelDataSize) { @@ -487,22 +508,22 @@ bufferedTileWrite (TiledOutputFile::Data *ofd, if (ofd->tileOffsets (dx, dy, lx, ly)) { - THROW (Iex::ArgExc, - "Attempt to write tile " - "(" << dx << ", " << dy << ", " << lx << "," << ly << ") " - "more than once."); + THROW (IEX_NAMESPACE::ArgExc, + "Attempt to write tile " + "(" << dx << ", " << dy << ", " << lx << ", " << ly << ") " + "more than once."); } // // If tiles can be written in random order, then don't buffer anything. // - + if (ofd->lineOrder == RANDOM_Y) { - writeTileData (ofd, dx, dy, lx, ly, pixelData, pixelDataSize); + writeTileData (streamData, ofd, dx, dy, lx, ly, pixelData, pixelDataSize); return; } - + // // If the tiles cannot be written in random order, then check if a // tile with coordinates (dx,dy,lx,ly) has already been buffered. @@ -512,10 +533,10 @@ bufferedTileWrite (TiledOutputFile::Data *ofd, if (ofd->tileMap.find (currentTile) != ofd->tileMap.end()) { - THROW (Iex::ArgExc, - "Attempt to write tile " - "(" << dx << ", " << dy << ", " << lx << "," << ly << ") " - "more than once."); + THROW (IEX_NAMESPACE::ArgExc, + "Attempt to write tile " + "(" << dx << ", " << dy << ", " << lx << ", " << ly << ") " + "more than once."); } // @@ -525,38 +546,39 @@ bufferedTileWrite (TiledOutputFile::Data *ofd, // // Otherwise, buffer the tile so it can be written to file later. // - + if (ofd->nextTileToWrite == currentTile) { - writeTileData (ofd, dx, dy, lx, ly, pixelData, pixelDataSize); + writeTileData (streamData, ofd, dx, dy, lx, ly, pixelData, pixelDataSize); ofd->nextTileToWrite = ofd->nextTileCoord (ofd->nextTileToWrite); TileMap::iterator i = ofd->tileMap.find (ofd->nextTileToWrite); - + // // Step through the tiles and write all successive buffered tiles after // the current one. // - + while(i != ofd->tileMap.end()) { // // Write the tile, and then delete the tile's buffered data // - writeTileData (ofd, - i->first.dx, i->first.dy, - i->first.lx, i->first.ly, - i->second->pixelData, - i->second->pixelDataSize); + writeTileData (streamData, + ofd, + i->first.dx, i->first.dy, + i->first.lx, i->first.ly, + i->second->pixelData, + i->second->pixelDataSize); delete i->second; ofd->tileMap.erase (i); - + // // Proceed to the next tile // - + ofd->nextTileToWrite = ofd->nextTileCoord (ofd->nextTileToWrite); i = ofd->tileMap.find (ofd->nextTileToWrite); } @@ -568,8 +590,8 @@ bufferedTileWrite (TiledOutputFile::Data *ofd, // insert it into the tileMap. // - ofd->tileMap[currentTile] = - new BufferedTile ((const char *)pixelData, pixelDataSize); + ofd->tileMap[currentTile] = + new BufferedTile ((const char *)pixelData, pixelDataSize); } } @@ -577,11 +599,11 @@ bufferedTileWrite (TiledOutputFile::Data *ofd, void convertToXdr (TiledOutputFile::Data *ofd, Array& tileBuffer, - int numScanLines, - int numPixelsPerScanLine) + int numScanLines, + int numPixelsPerScanLine) { // - // Convert the contents of a TiledOutputFile's tileBuffer from the + // Convert the contents of a TiledOutputFile's tileBuffer from the // machine's native representation to Xdr format. This function is called // by writeTile(), below, if the compressor wanted its input pixel data // in the machine's native format, but then failed to compress the data @@ -607,26 +629,26 @@ convertToXdr (TiledOutputFile::Data *ofd, for (int y = 0; y < numScanLines; ++y) { - // - // Iterate over all slices in the file. - // - - for (unsigned int i = 0; i < ofd->slices.size(); ++i) - { - const TOutSliceInfo &slice = ofd->slices[i]; - - // - // Convert the samples in place. - // - + // + // Iterate over all slices in the file. + // + + for (unsigned int i = 0; i < ofd->slices.size(); ++i) + { + const TOutSliceInfo &slice = ofd->slices[i]; + + // + // Convert the samples in place. + // + convertInPlace (writePtr, readPtr, slice.type, numPixelsPerScanLine); - } + } } #ifdef DEBUG - assert (writePtr == readPtr); + assert (writePtr == readPtr); #endif } @@ -641,17 +663,17 @@ convertToXdr (TiledOutputFile::Data *ofd, class TileBufferTask: public Task { public: - + TileBufferTask (TaskGroup *group, TiledOutputFile::Data *ofd, int number, - int dx, int dy, - int lx, int ly); - + int dx, int dy, + int lx, int ly); + virtual ~TileBufferTask (); virtual void execute (); - + private: TiledOutputFile::Data * _ofd; @@ -696,51 +718,51 @@ TileBufferTask::execute () { // // First copy the pixel data from the frame buffer - // into the tile buffer + // into the tile buffer // // Convert one tile's worth of pixel data to // a machine-independent representation, and store // the result in _tileBuffer->buffer. // - + char *writePtr = _tileBuffer->buffer; - - Box2i tileRange = Imf::dataWindowForTile (_ofd->tileDesc, + + Box2i tileRange = dataWindowForTile (_ofd->tileDesc, _ofd->minX, _ofd->maxX, _ofd->minY, _ofd->maxY, _tileBuffer->tileCoord.dx, _tileBuffer->tileCoord.dy, _tileBuffer->tileCoord.lx, _tileBuffer->tileCoord.ly); - + int numScanLines = tileRange.max.y - tileRange.min.y + 1; int numPixelsPerScanLine = tileRange.max.x - tileRange.min.x + 1; - + // // Iterate over the scan lines in the tile. // - + for (int y = tileRange.min.y; y <= tileRange.max.y; ++y) { // // Iterate over all image channels. // - + for (unsigned int i = 0; i < _ofd->slices.size(); ++i) { const TOutSliceInfo &slice = _ofd->slices[i]; - + // // These offsets are used to facilitate both absolute // and tile-relative pixel coordinates. // - + int xOffset = slice.xTileCoords * tileRange.min.x; int yOffset = slice.yTileCoords * tileRange.min.y; - - // - // Fill the tile buffer with pixel data. - // + + // + // Fill the tile buffer with pixel data. + // if (slice.zero) { @@ -748,7 +770,7 @@ TileBufferTask::execute () // The frame buffer contains no data for this channel. // Store zeroes in _data->tileBuffer. // - + fillChannelWithZeroes (writePtr, _ofd->format, slice.type, numPixelsPerScanLine); } @@ -757,7 +779,7 @@ TileBufferTask::execute () // // The frame buffer contains data for this channel. // - + const char *readPtr = slice.base + (y - yOffset) * slice.yStride + (tileRange.min.x - xOffset) * @@ -766,22 +788,22 @@ TileBufferTask::execute () const char *endPtr = readPtr + (numPixelsPerScanLine - 1) * slice.xStride; - + copyFromFrameBuffer (writePtr, readPtr, endPtr, slice.xStride, _ofd->format, slice.type); } } } - + // - // Compress the contents of the tileBuffer, + // Compress the contents of the tileBuffer, // and store the compressed data in the output file. // - + _tileBuffer->dataSize = writePtr - _tileBuffer->buffer; _tileBuffer->dataPtr = _tileBuffer->buffer; - + if (_tileBuffer->compressor) { const char *compPtr; @@ -790,7 +812,7 @@ TileBufferTask::execute () (_tileBuffer->dataPtr, _tileBuffer->dataSize, tileRange, compPtr); - + if (compSize < _tileBuffer->dataSize) { _tileBuffer->dataSize = compSize; @@ -803,7 +825,7 @@ TileBufferTask::execute () // we cannot write to the file using native format, // so we need to convert the lineBuffer to Xdr. // - + convertToXdr (_ofd, _tileBuffer->buffer, numScanLines, numPixelsPerScanLine); } @@ -835,58 +857,115 @@ TiledOutputFile::TiledOutputFile const Header &header, int numThreads) : - _data (new Data (true, numThreads)) + _data (new Data (numThreads)), + _streamData (new OutputStreamMutex()), + _deleteStream (true) { try { - header.sanityCheck (true); - _data->os = new StdOFStream (fileName); - initialize (header); + header.sanityCheck (true); + _streamData->os = new StdOFStream (fileName); + _data->multipart=false; // since we opened with one header we can't be multipart + initialize (header); + _streamData->currentPosition = _streamData->os->tellp(); + + // Write header and empty offset table to the file. + writeMagicNumberAndVersionField(*_streamData->os, _data->header); + _data->previewPosition = _data->header.writeTo (*_streamData->os, true); + _data->tileOffsetsPosition = _data->tileOffsets.writeTo (*_streamData->os); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - delete _data; + // ~TiledOutputFile will not run, so free memory here + delete _streamData->os; + delete _streamData; + delete _data; - REPLACE_EXC (e, "Cannot open image file " - "\"" << fileName << "\". " << e); - throw; + REPLACE_EXC (e, "Cannot open image file " + "\"" << fileName << "\". " << e.what()); + throw; } catch (...) { - delete _data; + // ~TiledOutputFile will not run, so free memory here + delete _streamData->os; + delete _streamData; + delete _data; throw; } } TiledOutputFile::TiledOutputFile - (OStream &os, + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header, int numThreads) : - _data (new Data (false, numThreads)) + _data (new Data (numThreads)), + _streamData (new OutputStreamMutex()), + _deleteStream (false) { try { - header.sanityCheck(true); - _data->os = &os; - initialize (header); + header.sanityCheck(true); + _streamData->os = &os; + _data->multipart=false; // since we opened with one header we can't be multipart + initialize (header); + _streamData->currentPosition = _streamData->os->tellp(); + + // Write header and empty offset table to the file. + writeMagicNumberAndVersionField(*_streamData->os, _data->header); + _data->previewPosition = _data->header.writeTo (*_streamData->os, true); + _data->tileOffsetsPosition = _data->tileOffsets.writeTo (*_streamData->os); + } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - delete _data; + delete _streamData; + delete _data; - REPLACE_EXC (e, "Cannot open image file " - "\"" << os.fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Cannot open image file " + "\"" << os.fileName() << "\". " << e.what()); + throw; } catch (...) { - delete _data; + delete _streamData; + delete _data; throw; } } +TiledOutputFile::TiledOutputFile(const OutputPartData* part) : + _deleteStream (false) +{ + try + { + if (part->header.type() != TILEDIMAGE) + throw IEX_NAMESPACE::ArgExc("Can't build a TiledOutputFile from a type-mismatched part."); + + _streamData = part->mutex; + _data = new Data(part->numThreads); + _data->multipart=part->multipart; + initialize(part->header); + _data->partNumber = part->partNumber; + _data->tileOffsetsPosition = part->chunkOffsetTablePosition; + _data->previewPosition = part->previewPosition; + } + catch (IEX_NAMESPACE::BaseExc &e) + { + delete _data; + + REPLACE_EXC (e, "Cannot initialize output part " + "\"" << part->partNumber << "\". " << e.what()); + throw; + } + catch (...) + { + delete _data; + throw; + } +} void TiledOutputFile::initialize (const Header &header) @@ -894,12 +973,25 @@ TiledOutputFile::initialize (const Header &header) _data->header = header; _data->lineOrder = _data->header.lineOrder(); + + // // Check that the file is indeed tiled // _data->tileDesc = _data->header.tileDescription(); + + // + // 'Fix' the type attribute if it exists but is incorrectly set + // (attribute is optional, but ensure it is correct if it exists) + // + if(_data->header.hasType()) + { + _data->header.setType(TILEDIMAGE); + } + + // // Save the dataWindow information // @@ -915,25 +1007,25 @@ TiledOutputFile::initialize (const Header &header) // precalculateTileInfo (_data->tileDesc, - _data->minX, _data->maxX, - _data->minY, _data->maxY, - _data->numXTiles, _data->numYTiles, - _data->numXLevels, _data->numYLevels); - + _data->minX, _data->maxX, + _data->minY, _data->maxY, + _data->numXTiles, _data->numYTiles, + _data->numXLevels, _data->numYLevels); + // // Determine the first tile coordinate that we will be writing // if the file is not RANDOM_Y. // - + _data->nextTileToWrite = (_data->lineOrder == INCREASING_Y)? - TileCoord (0, 0, 0, 0): - TileCoord (0, _data->numYTiles[0] - 1, 0, 0); + TileCoord (0, 0, 0, 0): + TileCoord (0, _data->numYTiles[0] - 1, 0, 0); _data->maxBytesPerTileLine = - calculateBytesPerPixel (_data->header) * _data->tileDesc.xSize; + calculateBytesPerPixel (_data->header) * _data->tileDesc.xSize; _data->tileBufferSize = _data->maxBytesPerTileLine * _data->tileDesc.ySize; - + // // Create all the TileBuffers and allocate their internal buffers // @@ -941,10 +1033,10 @@ TiledOutputFile::initialize (const Header &header) for (size_t i = 0; i < _data->tileBuffers.size(); i++) { _data->tileBuffers[i] = new TileBuffer (newTileCompressor - (_data->header.compression(), - _data->maxBytesPerTileLine, - _data->tileDesc.ySize, - _data->header)); + (_data->header.compression(), + _data->maxBytesPerTileLine, + _data->tileDesc.ySize, + _data->header)); _data->tileBuffers[i]->buffer.resizeErase(_data->tileBufferSize); } @@ -952,15 +1044,10 @@ TiledOutputFile::initialize (const Header &header) _data->format = defaultFormat (_data->tileBuffers[0]->compressor); _data->tileOffsets = TileOffsets (_data->tileDesc.mode, - _data->numXLevels, - _data->numYLevels, - _data->numXTiles, - _data->numYTiles); - - _data->previewPosition = _data->header.writeTo (*_data->os, true); - - _data->tileOffsetsPosition = _data->tileOffsets.writeTo (*_data->os); - _data->currentPosition = _data->os->tellp(); + _data->numXLevels, + _data->numYLevels, + _data->numXTiles, + _data->numYTiles); } @@ -969,12 +1056,20 @@ TiledOutputFile::~TiledOutputFile () if (_data) { { + Lock lock(*_streamData); + Int64 originalPosition = _streamData->os->tellp(); + if (_data->tileOffsetsPosition > 0) { try { - _data->os->seekp (_data->tileOffsetsPosition); - _data->tileOffsets.writeTo (*_data->os); + _streamData->os->seekp (_data->tileOffsetsPosition); + _data->tileOffsets.writeTo (*_streamData->os); + + // + // Restore the original position. + // + _streamData->os->seekp (originalPosition); } catch (...) { @@ -987,6 +1082,12 @@ TiledOutputFile::~TiledOutputFile () } } } + + if (_deleteStream && _streamData) + delete _streamData->os; + + if (_data->partNumber == -1) + delete _streamData; delete _data; } @@ -996,7 +1097,7 @@ TiledOutputFile::~TiledOutputFile () const char * TiledOutputFile::fileName () const { - return _data->os->fileName(); + return _streamData->os->fileName(); } @@ -1007,10 +1108,10 @@ TiledOutputFile::header () const } -void +void TiledOutputFile::setFrameBuffer (const FrameBuffer &frameBuffer) { - Lock lock (*_data); + Lock lock (*_streamData); // // Check if the new frame buffer descriptor @@ -1020,25 +1121,25 @@ TiledOutputFile::setFrameBuffer (const FrameBuffer &frameBuffer) const ChannelList &channels = _data->header.channels(); for (ChannelList::ConstIterator i = channels.begin(); - i != channels.end(); - ++i) + i != channels.end(); + ++i) { - FrameBuffer::ConstIterator j = frameBuffer.find (i.name()); + FrameBuffer::ConstIterator j = frameBuffer.find (i.name()); - if (j == frameBuffer.end()) - continue; + if (j == frameBuffer.end()) + continue; - if (i.channel().type != j.slice().type) - THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" channel " - "of output file \"" << fileName() << "\" is " - "not compatible with the frame buffer's " - "pixel type."); + if (i.channel().type != j.slice().type) + THROW (IEX_NAMESPACE::ArgExc, "Pixel type of \"" << i.name() << "\" channel " + "of output file \"" << fileName() << "\" is " + "not compatible with the frame buffer's " + "pixel type."); - if (j.slice().xSampling != 1 || j.slice().ySampling != 1) - THROW (Iex::ArgExc, "All channels in a tiled file must have" - "sampling (1,1)."); + if (j.slice().xSampling != 1 || j.slice().ySampling != 1) + THROW (IEX_NAMESPACE::ArgExc, "All channels in a tiled file must have" + "sampling (1,1)."); } - + // // Initialize slice table for writePixels(). // @@ -1046,38 +1147,38 @@ TiledOutputFile::setFrameBuffer (const FrameBuffer &frameBuffer) vector slices; for (ChannelList::ConstIterator i = channels.begin(); - i != channels.end(); - ++i) - { - FrameBuffer::ConstIterator j = frameBuffer.find (i.name()); - - if (j == frameBuffer.end()) - { - // - // Channel i is not present in the frame buffer. - // In the file, channel i will contain only zeroes. - // - - slices.push_back (TOutSliceInfo (i.channel().type, - 0, // base - 0, // xStride, - 0, // yStride, - true)); // zero - } - else + i != channels.end(); + ++i) { - // - // Channel i is present in the frame buffer. - // - - slices.push_back (TOutSliceInfo (j.slice().type, - j.slice().base, - j.slice().xStride, - j.slice().yStride, - false, // zero + FrameBuffer::ConstIterator j = frameBuffer.find (i.name()); + + if (j == frameBuffer.end()) + { + // + // Channel i is not present in the frame buffer. + // In the file, channel i will contain only zeroes. + // + + slices.push_back (TOutSliceInfo (i.channel().type, + 0, // base + 0, // xStride, + 0, // yStride, + true)); // zero + } + else + { + // + // Channel i is present in the frame buffer. + // + + slices.push_back (TOutSliceInfo (j.slice().type, + j.slice().base, + j.slice().xStride, + j.slice().yStride, + false, // zero (j.slice().xTileCoords)? 1: 0, (j.slice().yTileCoords)? 1: 0)); - } + } } // @@ -1092,67 +1193,72 @@ TiledOutputFile::setFrameBuffer (const FrameBuffer &frameBuffer) const FrameBuffer & TiledOutputFile::frameBuffer () const { - Lock lock (*_data); + Lock lock (*_streamData); return _data->frameBuffer; } -void +void TiledOutputFile::writeTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly) { try { - Lock lock (*_data); + Lock lock (*_streamData); if (_data->slices.size() == 0) - throw Iex::ArgExc ("No frame buffer specified " - "as pixel data source."); + throw IEX_NAMESPACE::ArgExc ("No frame buffer specified " + "as pixel data source."); - if (!isValidTile (dx1, dy1, lx, ly) || !isValidTile (dx2, dy2, lx, ly)) - throw Iex::ArgExc ("Tile coordinates are invalid."); + if (!isValidTile (dx1, dy1, lx, ly) || !isValidTile (dx2, dy2, lx, ly)) + throw IEX_NAMESPACE::ArgExc ("Tile coordinates are invalid."); + if (!isValidLevel (lx, ly)) + THROW (IEX_NAMESPACE::ArgExc, + "Level coordinate " + "(" << lx << ", " << ly << ") " + "is invalid."); // // Determine the first and last tile coordinates in both dimensions // based on the file's lineOrder // - + if (dx1 > dx2) swap (dx1, dx2); - + if (dy1 > dy2) swap (dy1, dy2); - + int dyStart = dy1; - int dyStop = dy2 + 1; - int dY = 1; - + int dyStop = dy2 + 1; + int dY = 1; + if (_data->lineOrder == DECREASING_Y) { dyStart = dy2; dyStop = dy1 - 1; dY = -1; } - + int numTiles = (dx2 - dx1 + 1) * (dy2 - dy1 + 1); int numTasks = min ((int)_data->tileBuffers.size(), numTiles); // // Create a task group for all tile buffer tasks. When the - // task group goes out of scope, the destructor waits until - // all tasks are complete. + // task group goes out of scope, the destructor waits until + // all tasks are complete. // { TaskGroup taskGroup; - + // // Add in the initial compression tasks to the thread pool // - + int nextCompBuffer = 0; - int dxComp = dx1; - int dyComp = dyStart; + int dxComp = dx1; + int dyComp = dyStart; while (nextCompBuffer < numTasks) { @@ -1169,61 +1275,61 @@ TiledOutputFile::writeTiles (int dx1, int dx2, int dy1, int dy2, dyComp += dY; } } - + // // Write the compressed buffers and add in more compression - // tasks until done + // tasks until done // - + int nextWriteBuffer = 0; - int dxWrite = dx1; - int dyWrite = dyStart; + int dxWrite = dx1; + int dyWrite = dyStart; while (nextWriteBuffer < numTiles) { - // + // // Wait until the nextWriteBuffer is ready to be written - // + // TileBuffer* writeBuffer = _data->getTileBuffer (nextWriteBuffer); writeBuffer->wait(); - - // + + // // Write the tilebuffer - // + // - bufferedTileWrite (_data, dxWrite, dyWrite, lx, ly, + bufferedTileWrite (_streamData, _data, dxWrite, dyWrite, lx, ly, writeBuffer->dataPtr, writeBuffer->dataSize); - - // + + // // Release the lock on nextWriteBuffer - // + // writeBuffer->post(); - - // + + // // If there are no more tileBuffers to compress, then - // only continue to write out remaining tileBuffers, - // otherwise keep adding compression tasks. - // + // only continue to write out remaining tileBuffers, + // otherwise keep adding compression tasks. + // if (nextCompBuffer < numTiles) { - // + // // add nextCompBuffer as a compression Task - // + // ThreadPool::addGlobalTask - (new TileBufferTask (&taskGroup, - _data, - nextCompBuffer, + (new TileBufferTask (&taskGroup, + _data, + nextCompBuffer, dxComp, dyComp, - lx, ly)); + lx, ly)); } - + nextWriteBuffer++; dxWrite++; @@ -1232,7 +1338,7 @@ TiledOutputFile::writeTiles (int dx1, int dx2, int dy1, int dy2, dxWrite = dx1; dyWrite += dY; } - + nextCompBuffer++; dxComp++; @@ -1243,58 +1349,58 @@ TiledOutputFile::writeTiles (int dx1, int dx2, int dy1, int dy2, } } - // + // // finish all tasks - // + // } - // - // Exeption handling: - // - // TileBufferTask::execute() may have encountered exceptions, but - // those exceptions occurred in another thread, not in the thread - // that is executing this call to TiledOutputFile::writeTiles(). - // TileBufferTask::execute() has caught all exceptions and stored - // the exceptions' what() strings in the tile buffers. - // Now we check if any tile buffer contains a stored exception; if - // this is the case then we re-throw the exception in this thread. - // (It is possible that multiple tile buffers contain stored - // exceptions. We re-throw the first exception we find and - // ignore all others.) - // - - const string *exception = 0; - - for (int i = 0; i < _data->tileBuffers.size(); ++i) - { + // + // Exeption handling: + // + // TileBufferTask::execute() may have encountered exceptions, but + // those exceptions occurred in another thread, not in the thread + // that is executing this call to TiledOutputFile::writeTiles(). + // TileBufferTask::execute() has caught all exceptions and stored + // the exceptions' what() strings in the tile buffers. + // Now we check if any tile buffer contains a stored exception; if + // this is the case then we re-throw the exception in this thread. + // (It is possible that multiple tile buffers contain stored + // exceptions. We re-throw the first exception we find and + // ignore all others.) + // + + const string *exception = 0; + + for (size_t i = 0; i < _data->tileBuffers.size(); ++i) + { TileBuffer *tileBuffer = _data->tileBuffers[i]; - if (tileBuffer->hasException && !exception) - exception = &tileBuffer->exception; + if (tileBuffer->hasException && !exception) + exception = &tileBuffer->exception; - tileBuffer->hasException = false; - } + tileBuffer->hasException = false; + } - if (exception) - throw Iex::IoExc (*exception); + if (exception) + throw IEX_NAMESPACE::IoExc (*exception); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { REPLACE_EXC (e, "Failed to write pixel data to image " - "file \"" << fileName() << "\". " << e); + "file \"" << fileName() << "\". " << e.what()); throw; } } -void +void TiledOutputFile::writeTiles (int dx1, int dxMax, int dyMin, int dyMax, int l) { writeTiles (dx1, dxMax, dyMin, dyMax, l, l); } -void +void TiledOutputFile::writeTile (int dx, int dy, int lx, int ly) { writeTiles (dx, dx, dy, dy, lx, ly); @@ -1308,10 +1414,10 @@ TiledOutputFile::writeTile (int dx, int dy, int l) } -void +void TiledOutputFile::copyPixels (TiledInputFile &in) { - Lock lock (*_data); + Lock lock (*_streamData); // // Check if this file's and and the InputFile's @@ -1319,43 +1425,43 @@ TiledOutputFile::copyPixels (TiledInputFile &in) // const Header &hdr = _data->header; - const Header &inHdr = in.header(); + const Header &inHdr = in.header(); if (!hdr.hasTileDescription() || !inHdr.hasTileDescription()) - THROW (Iex::ArgExc, "Cannot perform a quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\". The " + THROW (IEX_NAMESPACE::ArgExc, "Cannot perform a quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\". The " "output file is tiled, but the input file is not. " "Try using OutputFile::copyPixels() instead."); if (!(hdr.tileDescription() == inHdr.tileDescription())) - THROW (Iex::ArgExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\" failed. " - "The files have different tile descriptions."); + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files have different tile descriptions."); if (!(hdr.dataWindow() == inHdr.dataWindow())) - THROW (Iex::ArgExc, "Cannot copy pixels from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\". The " + THROW (IEX_NAMESPACE::ArgExc, "Cannot copy pixels from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\". The " "files have different data windows."); if (!(hdr.lineOrder() == inHdr.lineOrder())) - THROW (Iex::ArgExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\" failed. " - "The files have different line orders."); + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files have different line orders."); if (!(hdr.compression() == inHdr.compression())) - THROW (Iex::ArgExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\" failed. " - "The files use different compression methods."); + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" failed. " + "The files use different compression methods."); if (!(hdr.channels() == inHdr.channels())) - THROW (Iex::ArgExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << fileName() << "\" " + THROW (IEX_NAMESPACE::ArgExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << fileName() << "\" " "failed. The files have different channel " "lists."); @@ -1364,9 +1470,9 @@ TiledOutputFile::copyPixels (TiledInputFile &in) // if (!_data->tileOffsets.isEmpty()) - THROW (Iex::LogicExc, "Quick pixel copy from image " - "file \"" << in.fileName() << "\" to image " - "file \"" << _data->os->fileName() << "\" " + THROW (IEX_NAMESPACE::LogicExc, "Quick pixel copy from image " + "file \"" << in.fileName() << "\" to image " + "file \"" << _streamData->os->fileName() << "\" " "failed. \"" << fileName() << "\" " "already contains pixel data."); @@ -1381,47 +1487,91 @@ TiledOutputFile::copyPixels (TiledInputFile &in) case ONE_LEVEL: case MIPMAP_LEVELS: - for (size_t i_l = 0; i_l < numLevels (); ++i_l) + for (int i_l = 0; i_l < numLevels (); ++i_l) numAllTiles += numXTiles (i_l) * numYTiles (i_l); break; case RIPMAP_LEVELS: - for (size_t i_ly = 0; i_ly < numYLevels (); ++i_ly) - for (size_t i_lx = 0; i_lx < numXLevels (); ++i_lx) + for (int i_ly = 0; i_ly < numYLevels (); ++i_ly) + for (int i_lx = 0; i_lx < numXLevels (); ++i_lx) numAllTiles += numXTiles (i_lx) * numYTiles (i_ly); break; default: - throw Iex::ArgExc ("Unknown LevelMode format."); + throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format."); + } + + bool random_y = _data->lineOrder==RANDOM_Y; + + std::vector dx_table(random_y ? numAllTiles : 1); + std::vector dy_table(random_y ? numAllTiles : 1); + std::vector lx_table(random_y ? numAllTiles : 1); + std::vector ly_table(random_y ? numAllTiles : 1); + + if(random_y) + { + in.tileOrder(&dx_table[0],&dy_table[0],&lx_table[0],&ly_table[0]); + _data->nextTileToWrite.dx=dx_table[0]; + _data->nextTileToWrite.dy=dy_table[0]; + _data->nextTileToWrite.lx=lx_table[0]; + _data->nextTileToWrite.ly=ly_table[0]; } for (int i = 0; i < numAllTiles; ++i) { const char *pixelData; int pixelDataSize; - + int dx = _data->nextTileToWrite.dx; int dy = _data->nextTileToWrite.dy; int lx = _data->nextTileToWrite.lx; int ly = _data->nextTileToWrite.ly; + in.rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize); - writeTileData (_data, dx, dy, lx, ly, pixelData, pixelDataSize); + writeTileData (_streamData, _data, dx, dy, lx, ly, pixelData, pixelDataSize); + + if(random_y) + { + if(inextTileToWrite.dx=dx_table[i+1]; + _data->nextTileToWrite.dy=dy_table[i+1]; + _data->nextTileToWrite.lx=lx_table[i+1]; + _data->nextTileToWrite.ly=ly_table[i+1]; + } + }else{ + _data->nextTileToWrite=_data->nextTileCoord(_data->nextTileToWrite); + } } } -void +void TiledOutputFile::copyPixels (InputFile &in) { copyPixels (*in.tFile()); } +void +TiledOutputFile::copyPixels (InputPart &in) +{ + copyPixels (*in.file); +} + +void +TiledOutputFile::copyPixels (TiledInputPart &in) +{ + copyPixels (*in.file); +} + + + unsigned int TiledOutputFile::tileXSize () const { @@ -1454,9 +1604,9 @@ int TiledOutputFile::numLevels () const { if (levelMode() == RIPMAP_LEVELS) - THROW (Iex::LogicExc, "Error calling numLevels() on image " - "file \"" << fileName() << "\" " - "(numLevels() is not defined for RIPMAPs)."); + THROW (IEX_NAMESPACE::LogicExc, "Error calling numLevels() on image " + "file \"" << fileName() << "\" " + "(numLevels() is not defined for RIPMAPs)."); return _data->numXLevels; } @@ -1475,17 +1625,17 @@ TiledOutputFile::numYLevels () const } -bool +bool TiledOutputFile::isValidLevel (int lx, int ly) const { if (lx < 0 || ly < 0) - return false; + return false; if (levelMode() == MIPMAP_LEVELS && lx != ly) - return false; + return false; if (lx >= numXLevels() || ly >= numYLevels()) - return false; + return false; return true; } @@ -1496,16 +1646,16 @@ TiledOutputFile::levelWidth (int lx) const { try { - int retVal = levelSize (_data->minX, _data->maxX, lx, - _data->tileDesc.roundingMode); - + int retVal = levelSize (_data->minX, _data->maxX, lx, + _data->tileDesc.roundingMode); + return retVal; } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error calling levelWidth() on image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error calling levelWidth() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -1515,14 +1665,14 @@ TiledOutputFile::levelHeight (int ly) const { try { - return levelSize (_data->minY, _data->maxY, ly, - _data->tileDesc.roundingMode); + return levelSize (_data->minY, _data->maxY, ly, + _data->tileDesc.roundingMode); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error calling levelHeight() on image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error calling levelHeight() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -1531,9 +1681,9 @@ int TiledOutputFile::numXTiles (int lx) const { if (lx < 0 || lx >= _data->numXLevels) - THROW (Iex::LogicExc, "Error calling numXTiles() on image " - "file \"" << _data->os->fileName() << "\" " - "(Argument is not in valid range)."); + THROW (IEX_NAMESPACE::LogicExc, "Error calling numXTiles() on image " + "file \"" << _streamData->os->fileName() << "\" " + "(Argument is not in valid range)."); return _data->numXTiles[lx]; } @@ -1543,9 +1693,9 @@ int TiledOutputFile::numYTiles (int ly) const { if (ly < 0 || ly >= _data->numYLevels) - THROW (Iex::LogicExc, "Error calling numXTiles() on image " - "file \"" << _data->os->fileName() << "\" " - "(Argument is not in valid range)."); + THROW (IEX_NAMESPACE::LogicExc, "Error calling numXTiles() on image " + "file \"" << _streamData->os->fileName() << "\" " + "(Argument is not in valid range)."); return _data->numYTiles[ly]; } @@ -1563,16 +1713,17 @@ TiledOutputFile::dataWindowForLevel (int lx, int ly) const { try { - return Imf::dataWindowForLevel (_data->tileDesc, - _data->minX, _data->maxX, - _data->minY, _data->maxY, - lx, ly); + return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForLevel ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + lx, ly); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error calling dataWindowForLevel() on image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error calling dataWindowForLevel() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -1589,20 +1740,21 @@ TiledOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const { try { - if (!isValidTile (dx, dy, lx, ly)) - throw Iex::ArgExc ("Arguments not in valid range."); - - return Imf::dataWindowForTile (_data->tileDesc, - _data->minX, _data->maxX, - _data->minY, _data->maxY, - dx, dy, - lx, ly); + if (!isValidTile (dx, dy, lx, ly)) + throw IEX_NAMESPACE::ArgExc ("Arguments not in valid range."); + + return OPENEXR_IMF_INTERNAL_NAMESPACE::dataWindowForTile ( + _data->tileDesc, + _data->minX, _data->maxX, + _data->minY, _data->maxY, + dx, dy, + lx, ly); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Error calling dataWindowForTile() on image " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Error calling dataWindowForTile() on image " + "file \"" << fileName() << "\". " << e.what()); + throw; } } @@ -1611,35 +1763,35 @@ bool TiledOutputFile::isValidTile (int dx, int dy, int lx, int ly) const { return ((lx < _data->numXLevels && lx >= 0) && - (ly < _data->numYLevels && ly >= 0) && - (dx < _data->numXTiles[lx] && dx >= 0) && - (dy < _data->numYTiles[ly] && dy >= 0)); + (ly < _data->numYLevels && ly >= 0) && + (dx < _data->numXTiles[lx] && dx >= 0) && + (dy < _data->numYTiles[ly] && dy >= 0)); } void TiledOutputFile::updatePreviewImage (const PreviewRgba newPixels[]) { - Lock lock (*_data); + Lock lock (*_streamData); if (_data->previewPosition <= 0) - THROW (Iex::LogicExc, "Cannot update preview image pixels. " - "File \"" << fileName() << "\" does not " - "contain a preview image."); + THROW (IEX_NAMESPACE::LogicExc, "Cannot update preview image pixels. " + "File \"" << fileName() << "\" does not " + "contain a preview image."); // // Store the new pixels in the header's preview image attribute. // PreviewImageAttribute &pia = - _data->header.typedAttribute ("preview"); + _data->header.typedAttribute ("preview"); PreviewImage &pi = pia.value(); PreviewRgba *pixels = pi.pixels(); int numPixels = pi.width() * pi.height(); for (int i = 0; i < numPixels; ++i) - pixels[i] = newPixels[i]; + pixels[i] = newPixels[i]; // // Save the current file position, jump to the position in @@ -1647,47 +1799,47 @@ TiledOutputFile::updatePreviewImage (const PreviewRgba newPixels[]) // preview image, and jump back to the saved file position. // - Int64 savedPosition = _data->os->tellp(); + Int64 savedPosition = _streamData->os->tellp(); try { - _data->os->seekp (_data->previewPosition); - pia.writeValueTo (*_data->os, _data->version); - _data->os->seekp (savedPosition); + _streamData->os->seekp (_data->previewPosition); + pia.writeValueTo (*_streamData->os, _data->version); + _streamData->os->seekp (savedPosition); } - catch (Iex::BaseExc &e) + catch (IEX_NAMESPACE::BaseExc &e) { - REPLACE_EXC (e, "Cannot update preview image pixels for " - "file \"" << fileName() << "\". " << e); - throw; + REPLACE_EXC (e, "Cannot update preview image pixels for " + "file \"" << fileName() << "\". " << e.what()); + throw; } } void -TiledOutputFile::breakTile +TiledOutputFile::breakTile (int dx, int dy, int lx, int ly, int offset, int length, char c) { - Lock lock (*_data); + Lock lock (*_streamData); Int64 position = _data->tileOffsets (dx, dy, lx, ly); if (!position) - THROW (Iex::ArgExc, - "Cannot overwrite tile " - "(" << dx << ", " << dy << ", " << lx << "," << ly << "). " - "The tile has not yet been stored in " - "file \"" << fileName() << "\"."); + THROW (IEX_NAMESPACE::ArgExc, + "Cannot overwrite tile " + "(" << dx << ", " << dy << ", " << lx << "," << ly << "). " + "The tile has not yet been stored in " + "file \"" << fileName() << "\"."); - _data->currentPosition = 0; - _data->os->seekp (position + offset); + _streamData->currentPosition = 0; + _streamData->os->seekp (position + offset); for (int i = 0; i < length; ++i) - _data->os->write (&c, 1); + _streamData->os->write (&c, 1); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.h b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.h index 951c8a3cf6..bb75605f30 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.h +++ b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,20 +42,24 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" #include "ImathBox.h" -#include -#include +#include "ImfTileDescription.h" +#include "ImfThreading.h" +#include "ImfGenericOutputFile.h" +#include "ImfForward.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { -class TiledInputFile; -class InputFile; struct PreviewRgba; -class TiledOutputFile +class TiledOutputFile : public GenericOutputFile { public: @@ -80,9 +84,10 @@ class TiledOutputFile // faster than reading the tiles in random order (see writeTile, // below). //------------------------------------------------------------------- - + + IMF_EXPORT TiledOutputFile (const char fileName[], - const Header &header, + const Header &header, int numThreads = globalThreadCount ()); @@ -93,8 +98,9 @@ class TiledOutputFile // close the corresponding files. // ---------------------------------------------------------------- - TiledOutputFile (OStream &os, - const Header &header, + IMF_EXPORT + TiledOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, int numThreads = globalThreadCount ()); @@ -104,21 +110,24 @@ class TiledOutputFile // Destroying a TiledOutputFile object before all tiles // have been written results in an incomplete file. //----------------------------------------------------- - + + IMF_EXPORT virtual ~TiledOutputFile (); //------------------------ // Access to the file name //------------------------ - + + IMF_EXPORT const char * fileName () const; //-------------------------- // Access to the file header //-------------------------- - + + IMF_EXPORT const Header & header () const; @@ -132,14 +141,16 @@ class TiledOutputFile // called. The current frame buffer can be changed // after each call to writeTile(). //------------------------------------------------------- - + + IMF_EXPORT void setFrameBuffer (const FrameBuffer &frameBuffer); //----------------------------------- // Access to the current frame buffer //----------------------------------- - + + IMF_EXPORT const FrameBuffer & frameBuffer () const; @@ -153,9 +164,13 @@ class TiledOutputFile // fields of the file header's TileDescriptionAttribute. //--------------------------------------------------------- + IMF_EXPORT unsigned int tileXSize () const; + IMF_EXPORT unsigned int tileYSize () const; + IMF_EXPORT LevelMode levelMode () const; + IMF_EXPORT LevelRoundingMode levelRoundingMode () const; @@ -195,16 +210,20 @@ class TiledOutputFile // return value is the same as for numXLevels() // // if levelMode() == RIPMAP_LEVELS: - // an Iex::LogicExc exception is thrown + // an IEX_NAMESPACE::LogicExc exception is thrown // - // isValidLevel(lx, ly) returns true if the file contains + // isValidLevel(lx, ly) returns true if the file contains // a level with level number (lx, ly), false if not. // //-------------------------------------------------------------------- + IMF_EXPORT int numLevels () const; + IMF_EXPORT int numXLevels () const; + IMF_EXPORT int numYLevels () const; + IMF_EXPORT bool isValidLevel (int lx, int ly) const; @@ -226,7 +245,9 @@ class TiledOutputFile // //--------------------------------------------------------- + IMF_EXPORT int levelWidth (int lx) const; + IMF_EXPORT int levelHeight (int ly) const; @@ -250,7 +271,9 @@ class TiledOutputFile // //---------------------------------------------------------- + IMF_EXPORT int numXTiles (int lx = 0) const; + IMF_EXPORT int numYTiles (int ly = 0) const; @@ -274,8 +297,10 @@ class TiledOutputFile // //--------------------------------------------------------- - Imath::Box2i dataWindowForLevel (int l = 0) const; - Imath::Box2i dataWindowForLevel (int lx, int ly) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; //------------------------------------------------------------------- @@ -299,11 +324,13 @@ class TiledOutputFile // //------------------------------------------------------------------- - Imath::Box2i dataWindowForTile (int dx, int dy, - int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; - Imath::Box2i dataWindowForTile (int dx, int dy, - int lx, int ly) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; //------------------------------------------------------------------ // Write pixel data: @@ -343,10 +370,10 @@ class TiledOutputFile // in a contiguous block. The levels are ordered // like this: // - // (0, 0) (1, 0) ... (nx-1, 0) - // (0, 1) (1, 1) ... (nx-1, 1) + // (0, 0) (1, 0) ... (nx-1, 0) + // (0, 1) (1, 1) ... (nx-1, 1) // ... - // (0,ny-1) (1,ny-1) ... (nx-1,ny-1) + // (0,ny-1) (1,ny-1) ... (nx-1,ny-1) // // where nx = numXLevels(), and ny = numYLevels(). // In an individual level, (lx, ly), the tiles @@ -377,12 +404,16 @@ class TiledOutputFile // //------------------------------------------------------------------ + IMF_EXPORT void writeTile (int dx, int dy, int l = 0); + IMF_EXPORT void writeTile (int dx, int dy, int lx, int ly); + IMF_EXPORT void writeTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly); + IMF_EXPORT void writeTiles (int dx1, int dx2, int dy1, int dy2, int l = 0); @@ -394,10 +425,13 @@ class TiledOutputFile // header: The two header's "dataWindow", "compression", // "lineOrder", "channels", and "tiles" attributes must be the same. //------------------------------------------------------------------ - + + IMF_EXPORT void copyPixels (TiledInputFile &in); - - + IMF_EXPORT + void copyPixels (TiledInputPart &in); + + //------------------------------------------------------------------ // Shortcut to copy all pixels from an InputFile into this file, // without uncompressing and then recompressing the pixel data. @@ -407,9 +441,13 @@ class TiledOutputFile // // To use this function, the InputFile must be tiled. //------------------------------------------------------------------ - + + IMF_EXPORT void copyPixels (InputFile &in); + IMF_EXPORT + void copyPixels (InputPart &in); + //-------------------------------------------------------------- // Updating the preview image: @@ -417,7 +455,7 @@ class TiledOutputFile // updatePreviewImage() supplies a new set of pixels for the // preview image attribute in the file's header. If the header // does not contain a preview image, updatePreviewImage() throws - // an Iex::LogicExc. + // an IEX_NAMESPACE::LogicExc. // // Note: updatePreviewImage() is necessary because images are // often stored in a file incrementally, a few tiles at a time, @@ -429,12 +467,13 @@ class TiledOutputFile // //-------------------------------------------------------------- + IMF_EXPORT void updatePreviewImage (const PreviewRgba newPixels[]); //------------------------------------------------------------- // Break a tile -- for testing and debugging only: - // + // // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the // output file by writing n copies of character c, starting // p bytes from the beginning of the tile with tile coordinates @@ -446,30 +485,44 @@ class TiledOutputFile // //------------------------------------------------------------- + IMF_EXPORT void breakTile (int dx, int dy, - int lx, int ly, - int offset, - int length, - char c); + int lx, int ly, + int offset, + int length, + char c); struct Data; private: + // ---------------------------------------------------------------- + // A constructor attaches the OutputStreamMutex to the + // given one from MultiPartOutputFile. Set the previewPosition + // and lineOffsetsPosition which have been acquired from + // the constructor of MultiPartOutputFile as well. + // ---------------------------------------------------------------- + TiledOutputFile (const OutputPartData* part); + TiledOutputFile (const TiledOutputFile &); // not implemented TiledOutputFile & operator = (const TiledOutputFile &); // not implemented void initialize (const Header &header); bool isValidTile (int dx, int dy, - int lx, int ly) const; + int lx, int ly) const; size_t bytesPerLineForTile (int dx, int dy, - int lx, int ly) const; + int lx, int ly) const; Data * _data; + + OutputStreamMutex* _streamData; + bool _deleteStream; + + friend class MultiPartOutputFile; }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT #endif diff --git a/3rdparty/openexr/IlmImf/ImfTiledOutputPart.cpp b/3rdparty/openexr/IlmImf/ImfTiledOutputPart.cpp new file mode 100644 index 0000000000..cfa0e78e8d --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfTiledOutputPart.cpp @@ -0,0 +1,228 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfTiledOutputPart.h" +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +TiledOutputPart::TiledOutputPart(MultiPartOutputFile& multiPartFile, int partNumber) +{ + file = multiPartFile.getOutputPart(partNumber); +} + +const char * +TiledOutputPart::fileName () const +{ + return file->fileName(); +} + +const Header & +TiledOutputPart::header () const +{ + return file->header(); +} + +void +TiledOutputPart::setFrameBuffer (const FrameBuffer &frameBuffer) +{ + file->setFrameBuffer(frameBuffer); +} + +const FrameBuffer & +TiledOutputPart::frameBuffer () const +{ + return file->frameBuffer(); +} + +unsigned int +TiledOutputPart::tileXSize () const +{ + return file->tileXSize(); +} + +unsigned int +TiledOutputPart::tileYSize () const +{ + return file->tileYSize(); +} + +LevelMode +TiledOutputPart::levelMode () const +{ + return file->levelMode(); +} + +LevelRoundingMode +TiledOutputPart::levelRoundingMode () const +{ + return file->levelRoundingMode(); +} + +int +TiledOutputPart::numLevels () const +{ + return file->numLevels(); +} + +int +TiledOutputPart::numXLevels () const +{ + return file->numXLevels(); +} + +int +TiledOutputPart::numYLevels () const +{ + return file->numYLevels(); +} + +bool +TiledOutputPart::isValidLevel (int lx, int ly) const +{ + return file->isValidLevel(lx, ly); +} + +int +TiledOutputPart::levelWidth (int lx) const +{ + return file->levelWidth(lx); +} + +int +TiledOutputPart::levelHeight (int ly) const +{ + return file->levelHeight(ly); +} + +int +TiledOutputPart::numXTiles (int lx) const +{ + return file->numXTiles(lx); +} + +int +TiledOutputPart::numYTiles (int ly) const +{ + return file->numYTiles(ly); +} + +IMATH_NAMESPACE::Box2i +TiledOutputPart::dataWindowForLevel (int l) const +{ + return file->dataWindowForLevel(l); +} + +IMATH_NAMESPACE::Box2i +TiledOutputPart::dataWindowForLevel (int lx, int ly) const +{ + return file->dataWindowForLevel(lx, ly); +} + +IMATH_NAMESPACE::Box2i +TiledOutputPart::dataWindowForTile (int dx, int dy, int l) const +{ + return file->dataWindowForTile(dx, dy, l); +} + +IMATH_NAMESPACE::Box2i +TiledOutputPart::dataWindowForTile (int dx, int dy, int lx, int ly) const +{ + return file->dataWindowForTile(dx, dy, lx, ly); +} + +void +TiledOutputPart::writeTile (int dx, int dy, int l) +{ + file->writeTile(dx, dy, l); +} + +void +TiledOutputPart::writeTile (int dx, int dy, int lx, int ly) +{ + file->writeTile(dx, dy, lx, ly); +} + +void +TiledOutputPart::writeTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly) +{ + file->writeTiles(dx1, dx2, dy1, dy2, lx, ly); +} + +void +TiledOutputPart::writeTiles (int dx1, int dx2, int dy1, int dy2, int l) +{ + file->writeTiles(dx1, dx2, dy1, dy2, l); +} + +void +TiledOutputPart::copyPixels (TiledInputFile &in) +{ + file->copyPixels(in); +} + +void +TiledOutputPart::copyPixels (InputFile &in) +{ + file->copyPixels(in); +} + +void +TiledOutputPart::copyPixels (TiledInputPart &in) +{ + file->copyPixels(in); +} + +void +TiledOutputPart::copyPixels (InputPart &in) +{ + file->copyPixels(in); +} + + + +void +TiledOutputPart::updatePreviewImage (const PreviewRgba newPixels[]) +{ + file->updatePreviewImage(newPixels); +} + +void +TiledOutputPart::breakTile (int dx, int dy, int lx, int ly, int offset, int length, char c) +{ + file->breakTile(dx, dy, lx, ly, offset, length, c); +} + + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTiledOutputPart.h b/3rdparty/openexr/IlmImf/ImfTiledOutputPart.h new file mode 100644 index 0000000000..e7b3e2d38f --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfTiledOutputPart.h @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef IMFTILEDOUTPUTPART_H_ +#define IMFTILEDOUTPUTPART_H_ + +#include "ImfMultiPartOutputFile.h" +#include "ImfTiledOutputFile.h" +#include "ImfForward.h" +#include "ImfExport.h" +#include "ImfNamespace.h" + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + +//------------------------------------------------------------------------------- +// class TiledOutputPart: +// +// Same interface as TiledOutputFile. Please have a reference to TiledOutputFile. +//------------------------------------------------------------------------------- + +class TiledOutputPart +{ + public: + IMF_EXPORT + TiledOutputPart(MultiPartOutputFile& multiPartFile, int partNumber); + + IMF_EXPORT + const char * fileName () const; + IMF_EXPORT + const Header & header () const; + IMF_EXPORT + void setFrameBuffer (const FrameBuffer &frameBuffer); + IMF_EXPORT + const FrameBuffer & frameBuffer () const; + IMF_EXPORT + unsigned int tileXSize () const; + IMF_EXPORT + unsigned int tileYSize () const; + IMF_EXPORT + LevelMode levelMode () const; + IMF_EXPORT + LevelRoundingMode levelRoundingMode () const; + IMF_EXPORT + int numLevels () const; + IMF_EXPORT + int numXLevels () const; + IMF_EXPORT + int numYLevels () const; + IMF_EXPORT + bool isValidLevel (int lx, int ly) const; + IMF_EXPORT + int levelWidth (int lx) const; + IMF_EXPORT + int levelHeight (int ly) const; + IMF_EXPORT + int numXTiles (int lx = 0) const; + IMF_EXPORT + int numYTiles (int ly = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + IMF_EXPORT + void writeTile (int dx, int dy, int l = 0); + IMF_EXPORT + void writeTile (int dx, int dy, int lx, int ly); + IMF_EXPORT + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int lx, int ly); + IMF_EXPORT + void writeTiles (int dx1, int dx2, int dy1, int dy2, + int l = 0); + IMF_EXPORT + void copyPixels (TiledInputFile &in); + IMF_EXPORT + void copyPixels (InputFile &in); + IMF_EXPORT + void copyPixels (TiledInputPart &in); + IMF_EXPORT + void copyPixels (InputPart &in); + + + IMF_EXPORT + void updatePreviewImage (const PreviewRgba newPixels[]); + IMF_EXPORT + void breakTile (int dx, int dy, + int lx, int ly, + int offset, + int length, + char c); + + private: + TiledOutputFile* file; +}; + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif /* IMFTILEDOUTPUTPART_H_ */ diff --git a/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.cpp b/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.cpp index 0b20a69338..157aec0abe 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.cpp +++ b/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -51,51 +51,52 @@ #include "IlmThreadMutex.h" #include "Iex.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER using namespace std; -using namespace Imath; +using namespace IMATH_NAMESPACE; using namespace RgbaYca; -using namespace IlmThread; +using namespace ILMTHREAD_NAMESPACE; namespace { void insertChannels (Header &header, - RgbaChannels rgbaChannels, - const char fileName[]) + RgbaChannels rgbaChannels, + const char fileName[]) { ChannelList ch; if (rgbaChannels & (WRITE_Y | WRITE_C)) { - if (rgbaChannels & WRITE_Y) - { - ch.insert ("Y", Channel (HALF, 1, 1)); - } - - if (rgbaChannels & WRITE_C) - { - THROW (Iex::ArgExc, "Cannot open file \"" << fileName << "\" " - "for writing. Tiled image files do not " - "support subsampled chroma channels."); - } + if (rgbaChannels & WRITE_Y) + { + ch.insert ("Y", Channel (HALF, 1, 1)); + } + + if (rgbaChannels & WRITE_C) + { + THROW (IEX_NAMESPACE::ArgExc, "Cannot open file \"" << fileName << "\" " + "for writing. Tiled image files do not " + "support subsampled chroma channels."); + } } else { - if (rgbaChannels & WRITE_R) - ch.insert ("R", Channel (HALF, 1, 1)); + if (rgbaChannels & WRITE_R) + ch.insert ("R", Channel (HALF, 1, 1)); - if (rgbaChannels & WRITE_G) - ch.insert ("G", Channel (HALF, 1, 1)); + if (rgbaChannels & WRITE_G) + ch.insert ("G", Channel (HALF, 1, 1)); - if (rgbaChannels & WRITE_B) - ch.insert ("B", Channel (HALF, 1, 1)); + if (rgbaChannels & WRITE_B) + ch.insert ("B", Channel (HALF, 1, 1)); } if (rgbaChannels & WRITE_A) - ch.insert ("A", Channel (HALF, 1, 1)); + ch.insert ("A", Channel (HALF, 1, 1)); header.channels() = ch; } @@ -107,19 +108,19 @@ rgbaChannels (const ChannelList &ch, const string &channelNamePrefix = "") int i = 0; if (ch.findChannel (channelNamePrefix + "R")) - i |= WRITE_R; + i |= WRITE_R; if (ch.findChannel (channelNamePrefix + "G")) - i |= WRITE_G; - + i |= WRITE_G; + if (ch.findChannel (channelNamePrefix + "B")) - i |= WRITE_B; + i |= WRITE_B; if (ch.findChannel (channelNamePrefix + "A")) - i |= WRITE_A; + i |= WRITE_A; if (ch.findChannel (channelNamePrefix + "Y")) - i |= WRITE_Y; + i |= WRITE_Y; return RgbaChannels (i); } @@ -129,10 +130,10 @@ string prefixFromLayerName (const string &layerName, const Header &header) { if (layerName.empty()) - return ""; + return ""; if (hasMultiView (header) && multiView(header)[0] == layerName) - return ""; + return ""; return layerName + "."; } @@ -144,7 +145,7 @@ ywFromHeader (const Header &header) Chromaticities cr; if (hasChromaticities (header)) - cr = chromaticities (header); + cr = chromaticities (header); return computeYw (cr); } @@ -159,8 +160,8 @@ class TiledRgbaOutputFile::ToYa: public Mutex ToYa (TiledOutputFile &outputFile, RgbaChannels rgbaChannels); void setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride); + size_t xStride, + size_t yStride); void writeTile (int dx, int dy, int lx, int ly); @@ -179,12 +180,12 @@ class TiledRgbaOutputFile::ToYa: public Mutex TiledRgbaOutputFile::ToYa::ToYa (TiledOutputFile &outputFile, - RgbaChannels rgbaChannels) + RgbaChannels rgbaChannels) : _outputFile (outputFile) { _writeA = (rgbaChannels & WRITE_A)? true: false; - + const TileDescription &td = outputFile.header().tileDescription(); _tileXSize = td.xSize; @@ -199,8 +200,8 @@ TiledRgbaOutputFile::ToYa::ToYa (TiledOutputFile &outputFile, void TiledRgbaOutputFile::ToYa::setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride) + size_t xStride, + size_t yStride) { _fbBase = base; _fbXStride = xStride; @@ -213,9 +214,9 @@ TiledRgbaOutputFile::ToYa::writeTile (int dx, int dy, int lx, int ly) { if (_fbBase == 0) { - THROW (Iex::ArgExc, "No frame buffer was specified as the " - "pixel data source for image file " - "\"" << _outputFile.fileName() << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "No frame buffer was specified as the " + "pixel data source for image file " + "\"" << _outputFile.fileName() << "\"."); } // @@ -228,10 +229,10 @@ TiledRgbaOutputFile::ToYa::writeTile (int dx, int dy, int lx, int ly) for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1) { - for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1) - _buf[y1][x1] = _fbBase[x * _fbXStride + y * _fbYStride]; + for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1) + _buf[y1][x1] = _fbBase[x * _fbXStride + y * _fbYStride]; - RGBAtoYCA (_yw, width, _writeA, _buf[y1], _buf[y1]); + RGBAtoYCA (_yw, width, _writeA, _buf[y1], _buf[y1]); } // @@ -241,14 +242,14 @@ TiledRgbaOutputFile::ToYa::writeTile (int dx, int dy, int lx, int ly) FrameBuffer fb; fb.insert ("Y", Slice (HALF, // type - (char *) &_buf[-dw.min.y][-dw.min.x].g, // base - sizeof (Rgba), // xStride - sizeof (Rgba) * _tileXSize)); // yStride + (char *) &_buf[-dw.min.y][-dw.min.x].g, // base + sizeof (Rgba), // xStride + sizeof (Rgba) * _tileXSize)); // yStride fb.insert ("A", Slice (HALF, // type - (char *) &_buf[-dw.min.y][-dw.min.x].a, // base - sizeof (Rgba), // xStride - sizeof (Rgba) * _tileXSize)); // yStride + (char *) &_buf[-dw.min.y][-dw.min.x].a, // base + sizeof (Rgba), // xStride + sizeof (Rgba) * _tileXSize)); // yStride _outputFile.setFrameBuffer (fb); _outputFile.writeTile (dx, dy, lx, ly); @@ -274,13 +275,13 @@ TiledRgbaOutputFile::TiledRgbaOutputFile _outputFile = new TiledOutputFile (name, hd, numThreads); if (rgbaChannels & WRITE_Y) - _toYa = new ToYa (*_outputFile, rgbaChannels); + _toYa = new ToYa (*_outputFile, rgbaChannels); } TiledRgbaOutputFile::TiledRgbaOutputFile - (OStream &os, + (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header, RgbaChannels rgbaChannels, int tileXSize, @@ -298,7 +299,7 @@ TiledRgbaOutputFile::TiledRgbaOutputFile _outputFile = new TiledOutputFile (os, hd, numThreads); if (rgbaChannels & WRITE_Y) - _toYa = new ToYa (*_outputFile, rgbaChannels); + _toYa = new ToYa (*_outputFile, rgbaChannels); } @@ -309,11 +310,11 @@ TiledRgbaOutputFile::TiledRgbaOutputFile int tileYSize, LevelMode mode, LevelRoundingMode rmode, - const Imath::Box2i &displayWindow, - const Imath::Box2i &dataWindow, + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow, RgbaChannels rgbaChannels, float pixelAspectRatio, - const Imath::V2f screenWindowCenter, + const IMATH_NAMESPACE::V2f screenWindowCenter, float screenWindowWidth, LineOrder lineOrder, Compression compression, @@ -323,19 +324,19 @@ TiledRgbaOutputFile::TiledRgbaOutputFile _toYa (0) { Header hd (displayWindow, - dataWindow.isEmpty()? displayWindow: dataWindow, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + dataWindow.isEmpty()? displayWindow: dataWindow, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); insertChannels (hd, rgbaChannels, name); hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode)); _outputFile = new TiledOutputFile (name, hd, numThreads); if (rgbaChannels & WRITE_Y) - _toYa = new ToYa (*_outputFile, rgbaChannels); + _toYa = new ToYa (*_outputFile, rgbaChannels); } @@ -349,7 +350,7 @@ TiledRgbaOutputFile::TiledRgbaOutputFile LevelRoundingMode rmode, RgbaChannels rgbaChannels, float pixelAspectRatio, - const Imath::V2f screenWindowCenter, + const IMATH_NAMESPACE::V2f screenWindowCenter, float screenWindowWidth, LineOrder lineOrder, Compression compression, @@ -359,19 +360,19 @@ TiledRgbaOutputFile::TiledRgbaOutputFile _toYa (0) { Header hd (width, - height, - pixelAspectRatio, - screenWindowCenter, - screenWindowWidth, - lineOrder, - compression); + height, + pixelAspectRatio, + screenWindowCenter, + screenWindowWidth, + lineOrder, + compression); insertChannels (hd, rgbaChannels, name); hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode)); _outputFile = new TiledOutputFile (name, hd, numThreads); if (rgbaChannels & WRITE_Y) - _toYa = new ToYa (*_outputFile, rgbaChannels); + _toYa = new ToYa (*_outputFile, rgbaChannels); } @@ -384,27 +385,27 @@ TiledRgbaOutputFile::~TiledRgbaOutputFile () void TiledRgbaOutputFile::setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride) + size_t xStride, + size_t yStride) { if (_toYa) { - Lock lock (*_toYa); - _toYa->setFrameBuffer (base, xStride, yStride); + Lock lock (*_toYa); + _toYa->setFrameBuffer (base, xStride, yStride); } else { - size_t xs = xStride * sizeof (Rgba); - size_t ys = yStride * sizeof (Rgba); + size_t xs = xStride * sizeof (Rgba); + size_t ys = yStride * sizeof (Rgba); - FrameBuffer fb; + FrameBuffer fb; - fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys)); - fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys)); - fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys)); - fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys)); + fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys)); + fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys)); + fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys)); + fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys)); - _outputFile->setFrameBuffer (fb); + _outputFile->setFrameBuffer (fb); } } @@ -423,35 +424,35 @@ TiledRgbaOutputFile::frameBuffer () const } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & TiledRgbaOutputFile::displayWindow () const { return _outputFile->header().displayWindow(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & TiledRgbaOutputFile::dataWindow () const { return _outputFile->header().dataWindow(); } -float +float TiledRgbaOutputFile::pixelAspectRatio () const { return _outputFile->header().pixelAspectRatio(); } -const Imath::V2f +const IMATH_NAMESPACE::V2f TiledRgbaOutputFile::screenWindowCenter () const { return _outputFile->header().screenWindowCenter(); } -float +float TiledRgbaOutputFile::screenWindowWidth () const { return _outputFile->header().screenWindowWidth(); @@ -563,28 +564,28 @@ TiledRgbaOutputFile::numYTiles (int ly) const } -Imath::Box2i +IMATH_NAMESPACE::Box2i TiledRgbaOutputFile::dataWindowForLevel (int l) const { return _outputFile->dataWindowForLevel (l); } -Imath::Box2i +IMATH_NAMESPACE::Box2i TiledRgbaOutputFile::dataWindowForLevel (int lx, int ly) const { return _outputFile->dataWindowForLevel (lx, ly); } -Imath::Box2i +IMATH_NAMESPACE::Box2i TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int l) const { return _outputFile->dataWindowForTile (dx, dy, l); } -Imath::Box2i +IMATH_NAMESPACE::Box2i TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const { return _outputFile->dataWindowForTile (dx, dy, lx, ly); @@ -596,12 +597,12 @@ TiledRgbaOutputFile::writeTile (int dx, int dy, int l) { if (_toYa) { - Lock lock (*_toYa); - _toYa->writeTile (dx, dy, l, l); + Lock lock (*_toYa); + _toYa->writeTile (dx, dy, l, l); } else { - _outputFile->writeTile (dx, dy, l); + _outputFile->writeTile (dx, dy, l); } } @@ -611,27 +612,27 @@ TiledRgbaOutputFile::writeTile (int dx, int dy, int lx, int ly) { if (_toYa) { - Lock lock (*_toYa); - _toYa->writeTile (dx, dy, lx, ly); + Lock lock (*_toYa); + _toYa->writeTile (dx, dy, lx, ly); } else { - _outputFile->writeTile (dx, dy, lx, ly); + _outputFile->writeTile (dx, dy, lx, ly); } } -void +void TiledRgbaOutputFile::writeTiles (int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly) { if (_toYa) { - Lock lock (*_toYa); + Lock lock (*_toYa); for (int dy = dyMin; dy <= dyMax; dy++) for (int dx = dxMin; dx <= dxMax; dx++) - _toYa->writeTile (dx, dy, lx, ly); + _toYa->writeTile (dx, dy, lx, ly); } else { @@ -639,7 +640,7 @@ TiledRgbaOutputFile::writeTiles } } -void +void TiledRgbaOutputFile::writeTiles (int dxMin, int dxMax, int dyMin, int dyMax, int l) { @@ -654,9 +655,9 @@ class TiledRgbaInputFile::FromYa: public Mutex FromYa (TiledInputFile &inputFile); void setFrameBuffer (Rgba *base, - size_t xStride, - size_t yStride, - const string &channelNamePrefix); + size_t xStride, + size_t yStride, + const string &channelNamePrefix); void readTile (int dx, int dy, int lx, int ly); @@ -691,33 +692,33 @@ TiledRgbaInputFile::FromYa::FromYa (TiledInputFile &inputFile) void TiledRgbaInputFile::FromYa::setFrameBuffer (Rgba *base, - size_t xStride, - size_t yStride, - const string &channelNamePrefix) + size_t xStride, + size_t yStride, + const string &channelNamePrefix) { if (_fbBase == 0) { - FrameBuffer fb; - - fb.insert (channelNamePrefix + "Y", - Slice (HALF, // type - (char *) &_buf[0][0].g, // base - sizeof (Rgba), // xStride - sizeof (Rgba) * _tileXSize, // yStride - 1, 1, // sampling - 0.0, // fillValue - true, true)); // tileCoordinates - - fb.insert (channelNamePrefix + "A", - Slice (HALF, // type - (char *) &_buf[0][0].a, // base - sizeof (Rgba), // xStride - sizeof (Rgba) * _tileXSize, // yStride - 1, 1, // sampling - 1.0, // fillValue - true, true)); // tileCoordinates - - _inputFile.setFrameBuffer (fb); + FrameBuffer fb; + + fb.insert (channelNamePrefix + "Y", + Slice (HALF, // type + (char *) &_buf[0][0].g, // base + sizeof (Rgba), // xStride + sizeof (Rgba) * _tileXSize, // yStride + 1, 1, // sampling + 0.0, // fillValue + true, true)); // tileCoordinates + + fb.insert (channelNamePrefix + "A", + Slice (HALF, // type + (char *) &_buf[0][0].a, // base + sizeof (Rgba), // xStride + sizeof (Rgba) * _tileXSize, // yStride + 1, 1, // sampling + 1.0, // fillValue + true, true)); // tileCoordinates + + _inputFile.setFrameBuffer (fb); } _fbBase = base; @@ -731,15 +732,15 @@ TiledRgbaInputFile::FromYa::readTile (int dx, int dy, int lx, int ly) { if (_fbBase == 0) { - THROW (Iex::ArgExc, "No frame buffer was specified as the " - "pixel data destination for image file " - "\"" << _inputFile.fileName() << "\"."); + THROW (IEX_NAMESPACE::ArgExc, "No frame buffer was specified as the " + "pixel data destination for image file " + "\"" << _inputFile.fileName() << "\"."); } // // Read the tile requested by the caller into _buf. // - + _inputFile.readTile (dx, dy, lx, ly); // @@ -752,18 +753,18 @@ TiledRgbaInputFile::FromYa::readTile (int dx, int dy, int lx, int ly) for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1) { - for (int x1 = 0; x1 < width; ++x1) - { - _buf[y1][x1].r = 0; - _buf[y1][x1].b = 0; - } - - YCAtoRGBA (_yw, width, _buf[y1], _buf[y1]); - - for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1) - { - _fbBase[x * _fbXStride + y * _fbYStride] = _buf[y1][x1]; - } + for (int x1 = 0; x1 < width; ++x1) + { + _buf[y1][x1].r = 0; + _buf[y1][x1].b = 0; + } + + YCAtoRGBA (_yw, width, _buf[y1], _buf[y1]); + + for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1) + { + _fbBase[x * _fbXStride + y * _fbYStride] = _buf[y1][x1]; + } } } @@ -774,43 +775,43 @@ TiledRgbaInputFile::TiledRgbaInputFile (const char name[], int numThreads): _channelNamePrefix ("") { if (channels() & WRITE_Y) - _fromYa = new FromYa (*_inputFile); + _fromYa = new FromYa (*_inputFile); } -TiledRgbaInputFile::TiledRgbaInputFile (IStream &is, int numThreads): +TiledRgbaInputFile::TiledRgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads): _inputFile (new TiledInputFile (is, numThreads)), _fromYa (0), _channelNamePrefix ("") { if (channels() & WRITE_Y) - _fromYa = new FromYa (*_inputFile); + _fromYa = new FromYa (*_inputFile); } TiledRgbaInputFile::TiledRgbaInputFile (const char name[], - const string &layerName, - int numThreads) + const string &layerName, + int numThreads) : _inputFile (new TiledInputFile (name, numThreads)), _fromYa (0), _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header())) { if (channels() & WRITE_Y) - _fromYa = new FromYa (*_inputFile); + _fromYa = new FromYa (*_inputFile); } -TiledRgbaInputFile::TiledRgbaInputFile (IStream &is, - const string &layerName, - int numThreads) +TiledRgbaInputFile::TiledRgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + const string &layerName, + int numThreads) : _inputFile (new TiledInputFile (is, numThreads)), _fromYa (0), _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header())) { if (channels() & WRITE_Y) - _fromYa = new FromYa (*_inputFile); + _fromYa = new FromYa (*_inputFile); } @@ -821,64 +822,64 @@ TiledRgbaInputFile::~TiledRgbaInputFile () } -void +void TiledRgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride) { if (_fromYa) { - Lock lock (*_fromYa); - _fromYa->setFrameBuffer (base, xStride, yStride, _channelNamePrefix); + Lock lock (*_fromYa); + _fromYa->setFrameBuffer (base, xStride, yStride, _channelNamePrefix); } else { - size_t xs = xStride * sizeof (Rgba); - size_t ys = yStride * sizeof (Rgba); - - FrameBuffer fb; - - fb.insert (_channelNamePrefix + "R", - Slice (HALF, - (char *) &base[0].r, - xs, ys, - 1, 1, // xSampling, ySampling - 0.0)); // fillValue - - fb.insert (_channelNamePrefix + "G", - Slice (HALF, - (char *) &base[0].g, - xs, ys, - 1, 1, // xSampling, ySampling - 0.0)); // fillValue - - fb.insert (_channelNamePrefix + "B", - Slice (HALF, - (char *) &base[0].b, - xs, ys, - 1, 1, // xSampling, ySampling - 0.0)); // fillValue - - fb.insert (_channelNamePrefix + "A", - Slice (HALF, - (char *) &base[0].a, - xs, ys, - 1, 1, // xSampling, ySampling - 1.0)); // fillValue - - _inputFile->setFrameBuffer (fb); + size_t xs = xStride * sizeof (Rgba); + size_t ys = yStride * sizeof (Rgba); + + FrameBuffer fb; + + fb.insert (_channelNamePrefix + "R", + Slice (HALF, + (char *) &base[0].r, + xs, ys, + 1, 1, // xSampling, ySampling + 0.0)); // fillValue + + fb.insert (_channelNamePrefix + "G", + Slice (HALF, + (char *) &base[0].g, + xs, ys, + 1, 1, // xSampling, ySampling + 0.0)); // fillValue + + fb.insert (_channelNamePrefix + "B", + Slice (HALF, + (char *) &base[0].b, + xs, ys, + 1, 1, // xSampling, ySampling + 0.0)); // fillValue + + fb.insert (_channelNamePrefix + "A", + Slice (HALF, + (char *) &base[0].a, + xs, ys, + 1, 1, // xSampling, ySampling + 1.0)); // fillValue + + _inputFile->setFrameBuffer (fb); } } -void +void TiledRgbaInputFile::setLayerName (const std::string &layerName) { delete _fromYa; _fromYa = 0; - + _channelNamePrefix = prefixFromLayerName (layerName, _inputFile->header()); if (channels() & WRITE_Y) - _fromYa = new FromYa (*_inputFile); + _fromYa = new FromYa (*_inputFile); FrameBuffer fb; _inputFile->setFrameBuffer (fb); @@ -899,42 +900,42 @@ TiledRgbaInputFile::fileName () const } -const FrameBuffer & +const FrameBuffer & TiledRgbaInputFile::frameBuffer () const { return _inputFile->frameBuffer(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & TiledRgbaInputFile::displayWindow () const { return _inputFile->header().displayWindow(); } -const Imath::Box2i & +const IMATH_NAMESPACE::Box2i & TiledRgbaInputFile::dataWindow () const { return _inputFile->header().dataWindow(); } -float +float TiledRgbaInputFile::pixelAspectRatio () const { return _inputFile->header().pixelAspectRatio(); } -const Imath::V2f +const IMATH_NAMESPACE::V2f TiledRgbaInputFile::screenWindowCenter () const { return _inputFile->header().screenWindowCenter(); } -float +float TiledRgbaInputFile::screenWindowWidth () const { return _inputFile->header().screenWindowWidth(); @@ -955,7 +956,7 @@ TiledRgbaInputFile::compression () const } -RgbaChannels +RgbaChannels TiledRgbaInputFile::channels () const { return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix); @@ -1060,28 +1061,28 @@ TiledRgbaInputFile::numYTiles (int ly) const } -Imath::Box2i +IMATH_NAMESPACE::Box2i TiledRgbaInputFile::dataWindowForLevel (int l) const { return _inputFile->dataWindowForLevel (l); } -Imath::Box2i +IMATH_NAMESPACE::Box2i TiledRgbaInputFile::dataWindowForLevel (int lx, int ly) const { return _inputFile->dataWindowForLevel (lx, ly); } -Imath::Box2i +IMATH_NAMESPACE::Box2i TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int l) const { return _inputFile->dataWindowForTile (dx, dy, l); } -Imath::Box2i +IMATH_NAMESPACE::Box2i TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const { return _inputFile->dataWindowForTile (dx, dy, lx, ly); @@ -1093,12 +1094,12 @@ TiledRgbaInputFile::readTile (int dx, int dy, int l) { if (_fromYa) { - Lock lock (*_fromYa); - _fromYa->readTile (dx, dy, l, l); + Lock lock (*_fromYa); + _fromYa->readTile (dx, dy, l, l); } else { - _inputFile->readTile (dx, dy, l); + _inputFile->readTile (dx, dy, l); } } @@ -1108,27 +1109,27 @@ TiledRgbaInputFile::readTile (int dx, int dy, int lx, int ly) { if (_fromYa) { - Lock lock (*_fromYa); - _fromYa->readTile (dx, dy, lx, ly); + Lock lock (*_fromYa); + _fromYa->readTile (dx, dy, lx, ly); } else { - _inputFile->readTile (dx, dy, lx, ly); + _inputFile->readTile (dx, dy, lx, ly); } } -void +void TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly) { if (_fromYa) { - Lock lock (*_fromYa); + Lock lock (*_fromYa); for (int dy = dyMin; dy <= dyMax; dy++) for (int dx = dxMin; dx <= dxMax; dx++) - _fromYa->readTile (dx, dy, lx, ly); + _fromYa->readTile (dx, dy, lx, ly); } else { @@ -1136,7 +1137,7 @@ TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax, } } -void +void TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax, int l) { @@ -1144,19 +1145,19 @@ TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax, } -void +void TiledRgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[]) { _outputFile->updatePreviewImage (newPixels); } -void +void TiledRgbaOutputFile::breakTile (int dx, int dy, int lx, int ly, - int offset, int length, char c) + int offset, int length, char c) { _outputFile->breakTile (dx, dy, lx, ly, offset, length, c); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.h b/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.h index a23d159005..e12faab1fe 100644 --- a/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.h +++ b/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -45,21 +45,20 @@ // //----------------------------------------------------------------------------- -#include -#include +#include "ImfHeader.h" +#include "ImfFrameBuffer.h" #include "ImathVec.h" #include "ImathBox.h" #include "half.h" -#include -#include -#include +#include "ImfTileDescription.h" +#include "ImfRgba.h" +#include "ImfThreading.h" #include +#include "ImfNamespace.h" +#include "ImfForward.h" -namespace Imf { -class TiledOutputFile; -class TiledInputFile; -struct PreviewRgba; +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER // @@ -78,13 +77,14 @@ class TiledRgbaOutputFile // constructor. //--------------------------------------------------- + IMF_EXPORT TiledRgbaOutputFile (const char name[], - const Header &header, - RgbaChannels rgbaChannels, - int tileXSize, - int tileYSize, - LevelMode mode, - LevelRoundingMode rmode = ROUND_DOWN, + const Header &header, + RgbaChannels rgbaChannels, + int tileXSize, + int tileYSize, + LevelMode mode, + LevelRoundingMode rmode = ROUND_DOWN, int numThreads = globalThreadCount ()); @@ -97,13 +97,14 @@ class TiledRgbaOutputFile // corresponding files. //--------------------------------------------------- - TiledRgbaOutputFile (OStream &os, - const Header &header, - RgbaChannels rgbaChannels, - int tileXSize, - int tileYSize, - LevelMode mode, - LevelRoundingMode rmode = ROUND_DOWN, + IMF_EXPORT + TiledRgbaOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, + const Header &header, + RgbaChannels rgbaChannels, + int tileXSize, + int tileYSize, + LevelMode mode, + LevelRoundingMode rmode = ROUND_DOWN, int numThreads = globalThreadCount ()); @@ -113,20 +114,21 @@ class TiledRgbaOutputFile // "same as displayWindow") //------------------------------------------------------ + IMF_EXPORT TiledRgbaOutputFile (const char name[], - int tileXSize, - int tileYSize, - LevelMode mode, - LevelRoundingMode rmode, - const Imath::Box2i &displayWindow, - const Imath::Box2i &dataWindow = Imath::Box2i(), - RgbaChannels rgbaChannels = WRITE_RGBA, - float pixelAspectRatio = 1, - const Imath::V2f screenWindowCenter = - Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression compression = ZIP_COMPRESSION, + int tileXSize, + int tileYSize, + LevelMode mode, + LevelRoundingMode rmode, + const IMATH_NAMESPACE::Box2i &displayWindow, + const IMATH_NAMESPACE::Box2i &dataWindow = IMATH_NAMESPACE::Box2i(), + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = + IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = ZIP_COMPRESSION, int numThreads = globalThreadCount ()); @@ -136,23 +138,24 @@ class TiledRgbaOutputFile // Box2i (V2i (0, 0), V2i (width - 1, height -1)) //----------------------------------------------- + IMF_EXPORT TiledRgbaOutputFile (const char name[], - int width, - int height, - int tileXSize, - int tileYSize, - LevelMode mode, - LevelRoundingMode rmode = ROUND_DOWN, - RgbaChannels rgbaChannels = WRITE_RGBA, - float pixelAspectRatio = 1, - const Imath::V2f screenWindowCenter = - Imath::V2f (0, 0), - float screenWindowWidth = 1, - LineOrder lineOrder = INCREASING_Y, - Compression compression = ZIP_COMPRESSION, + int width, + int height, + int tileXSize, + int tileYSize, + LevelMode mode, + LevelRoundingMode rmode = ROUND_DOWN, + RgbaChannels rgbaChannels = WRITE_RGBA, + float pixelAspectRatio = 1, + const IMATH_NAMESPACE::V2f screenWindowCenter = + IMATH_NAMESPACE::V2f (0, 0), + float screenWindowWidth = 1, + LineOrder lineOrder = INCREASING_Y, + Compression compression = ZIP_COMPRESSION, int numThreads = globalThreadCount ()); - + IMF_EXPORT virtual ~TiledRgbaOutputFile (); @@ -164,23 +167,34 @@ class TiledRgbaOutputFile // //------------------------------------------------ + IMF_EXPORT void setFrameBuffer (const Rgba *base, - size_t xStride, - size_t yStride); + size_t xStride, + size_t yStride); //-------------------------- // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; + IMF_EXPORT const FrameBuffer & frameBuffer () const; - const Imath::Box2i & displayWindow () const; - const Imath::Box2i & dataWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & displayWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & dataWindow () const; + IMF_EXPORT float pixelAspectRatio () const; - const Imath::V2f screenWindowCenter () const; + IMF_EXPORT + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + IMF_EXPORT float screenWindowWidth () const; + IMF_EXPORT LineOrder lineOrder () const; + IMF_EXPORT Compression compression () const; + IMF_EXPORT RgbaChannels channels () const; @@ -188,30 +202,46 @@ class TiledRgbaOutputFile // Utility functions (same as in Imf::TiledOutputFile) //---------------------------------------------------- + IMF_EXPORT unsigned int tileXSize () const; + IMF_EXPORT unsigned int tileYSize () const; + IMF_EXPORT LevelMode levelMode () const; + IMF_EXPORT LevelRoundingMode levelRoundingMode () const; + IMF_EXPORT int numLevels () const; + IMF_EXPORT int numXLevels () const; + IMF_EXPORT int numYLevels () const; + IMF_EXPORT bool isValidLevel (int lx, int ly) const; + IMF_EXPORT int levelWidth (int lx) const; + IMF_EXPORT int levelHeight (int ly) const; + IMF_EXPORT int numXTiles (int lx = 0) const; + IMF_EXPORT int numYTiles (int ly = 0) const; - Imath::Box2i dataWindowForLevel (int l = 0) const; - Imath::Box2i dataWindowForLevel (int lx, int ly) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; - Imath::Box2i dataWindowForTile (int dx, int dy, - int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; - Imath::Box2i dataWindowForTile (int dx, int dy, - int lx, int ly) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; //------------------------------------------------------------------ // Write pixel data: @@ -241,12 +271,16 @@ class TiledRgbaOutputFile // //------------------------------------------------------------------ + IMF_EXPORT void writeTile (int dx, int dy, int l = 0); + IMF_EXPORT void writeTile (int dx, int dy, int lx, int ly); + IMF_EXPORT void writeTiles (int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly); + IMF_EXPORT void writeTiles (int dxMin, int dxMax, int dyMin, int dyMax, int l = 0); @@ -255,6 +289,7 @@ class TiledRgbaOutputFile // Update the preview image (see Imf::TiledOutputFile::updatePreviewImage()) // ------------------------------------------------------------------------- + IMF_EXPORT void updatePreviewImage (const PreviewRgba[]); @@ -269,18 +304,19 @@ class TiledRgbaOutputFile // //------------------------------------------------ + IMF_EXPORT void breakTile (int dx, int dy, - int lx, int ly, - int offset, - int length, - char c); + int lx, int ly, + int offset, + int length, + char c); private: // // Copy constructor and assignment are not implemented // - TiledRgbaOutputFile (const TiledRgbaOutputFile &); + TiledRgbaOutputFile (const TiledRgbaOutputFile &); TiledRgbaOutputFile & operator = (const TiledRgbaOutputFile &); class ToYa; @@ -306,6 +342,7 @@ class TiledRgbaInputFile // files. //-------------------------------------------------------- + IMF_EXPORT TiledRgbaInputFile (const char name[], int numThreads = globalThreadCount ()); @@ -319,7 +356,8 @@ class TiledRgbaInputFile // corresponding files. //------------------------------------------------------- - TiledRgbaInputFile (IStream &is, int numThreads = globalThreadCount ()); + IMF_EXPORT + TiledRgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads = globalThreadCount ()); //------------------------------------------------------------ @@ -328,18 +366,21 @@ class TiledRgbaInputFile // expected to be layerName.R, layerName.G, etc. //------------------------------------------------------------ + IMF_EXPORT TiledRgbaInputFile (const char name[], - const std::string &layerName, - int numThreads = globalThreadCount()); + const std::string &layerName, + int numThreads = globalThreadCount()); - TiledRgbaInputFile (IStream &is, - const std::string &layerName, - int numThreads = globalThreadCount()); + IMF_EXPORT + TiledRgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + const std::string &layerName, + int numThreads = globalThreadCount()); //----------- // Destructor //----------- + IMF_EXPORT virtual ~TiledRgbaInputFile (); @@ -351,9 +392,10 @@ class TiledRgbaInputFile // //----------------------------------------------------- + IMF_EXPORT void setFrameBuffer (Rgba *base, - size_t xStride, - size_t yStride); + size_t xStride, + size_t yStride); //------------------------------------------------------------------- // Switch to a different layer -- subsequent calls to readTile() @@ -362,6 +404,7 @@ class TiledRgbaInputFile // at least once before the next call to readTile() or readTiles(). //------------------------------------------------------------------- + IMF_EXPORT void setLayerName (const std::string &layerName); @@ -369,23 +412,36 @@ class TiledRgbaInputFile // Access to the file header //-------------------------- + IMF_EXPORT const Header & header () const; + IMF_EXPORT const FrameBuffer & frameBuffer () const; - const Imath::Box2i & displayWindow () const; - const Imath::Box2i & dataWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & displayWindow () const; + IMF_EXPORT + const IMATH_NAMESPACE::Box2i & dataWindow () const; + IMF_EXPORT float pixelAspectRatio () const; - const Imath::V2f screenWindowCenter () const; + IMF_EXPORT + const IMATH_NAMESPACE::V2f screenWindowCenter () const; + IMF_EXPORT float screenWindowWidth () const; + IMF_EXPORT LineOrder lineOrder () const; + IMF_EXPORT Compression compression () const; + IMF_EXPORT RgbaChannels channels () const; + IMF_EXPORT const char * fileName () const; + IMF_EXPORT bool isComplete () const; //---------------------------------- // Access to the file format version //---------------------------------- + IMF_EXPORT int version () const; @@ -393,31 +449,47 @@ class TiledRgbaInputFile // Utility functions (same as in Imf::TiledInputFile) //--------------------------------------------------- + IMF_EXPORT unsigned int tileXSize () const; + IMF_EXPORT unsigned int tileYSize () const; + IMF_EXPORT LevelMode levelMode () const; + IMF_EXPORT LevelRoundingMode levelRoundingMode () const; + IMF_EXPORT int numLevels () const; + IMF_EXPORT int numXLevels () const; + IMF_EXPORT int numYLevels () const; + IMF_EXPORT bool isValidLevel (int lx, int ly) const; + IMF_EXPORT int levelWidth (int lx) const; + IMF_EXPORT int levelHeight (int ly) const; + IMF_EXPORT int numXTiles (int lx = 0) const; + IMF_EXPORT int numYTiles (int ly = 0) const; - Imath::Box2i dataWindowForLevel (int l = 0) const; - Imath::Box2i dataWindowForLevel (int lx, int ly) const; - - Imath::Box2i dataWindowForTile (int dx, int dy, - int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForLevel (int lx, int ly) const; - Imath::Box2i dataWindowForTile (int dx, int dy, - int lx, int ly) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int l = 0) const; + IMF_EXPORT + IMATH_NAMESPACE::Box2i dataWindowForTile (int dx, int dy, + int lx, int ly) const; + //---------------------------------------------------------------- // Read pixel data: @@ -448,12 +520,16 @@ class TiledRgbaInputFile // //---------------------------------------------------------------- + IMF_EXPORT void readTile (int dx, int dy, int l = 0); + IMF_EXPORT void readTile (int dx, int dy, int lx, int ly); + IMF_EXPORT void readTiles (int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly); + IMF_EXPORT void readTiles (int dxMin, int dxMax, int dyMin, int dyMax, int l = 0); @@ -474,6 +550,10 @@ class TiledRgbaInputFile }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfTimeCode.cpp b/3rdparty/openexr/IlmImf/ImfTimeCode.cpp index fd4a7ed549..88b9d1c596 100644 --- a/3rdparty/openexr/IlmImf/ImfTimeCode.cpp +++ b/3rdparty/openexr/IlmImf/ImfTimeCode.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -36,15 +36,16 @@ //----------------------------------------------------------------------------- // // class TimeCode -// +// //----------------------------------------------------------------------------- #include #include "Iex.h" +#include "ImfNamespace.h" -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + TimeCode::TimeCode () { _time = 0; @@ -118,6 +119,21 @@ TimeCode::operator = (const TimeCode &other) return *this; } + +bool +TimeCode::operator == (const TimeCode & c) const +{ + return (_time == c._time && _user == c._user); +} + + +bool +TimeCode::operator != (const TimeCode & c) const +{ + return (_time != c._time || _user != c._user); +} + + namespace { @@ -169,8 +185,8 @@ void TimeCode::setHours (int value) { if (value < 0 || value > 23) - throw Iex::ArgExc ("Cannot set hours field in time code. " - "New value is out of range."); + throw IEX_NAMESPACE::ArgExc ("Cannot set hours field in time code. " + "New value is out of range."); setBitField (_time, 24, 29, binaryToBcd (value)); } @@ -187,8 +203,8 @@ void TimeCode::setMinutes (int value) { if (value < 0 || value > 59) - throw Iex::ArgExc ("Cannot set minutes field in time code. " - "New value is out of range."); + throw IEX_NAMESPACE::ArgExc ("Cannot set minutes field in time code. " + "New value is out of range."); setBitField (_time, 16, 22, binaryToBcd (value)); } @@ -205,8 +221,8 @@ void TimeCode::setSeconds (int value) { if (value < 0 || value > 59) - throw Iex::ArgExc ("Cannot set seconds field in time code. " - "New value is out of range."); + throw IEX_NAMESPACE::ArgExc ("Cannot set seconds field in time code. " + "New value is out of range."); setBitField (_time, 8, 14, binaryToBcd (value)); } @@ -223,8 +239,8 @@ void TimeCode::setFrame (int value) { if (value < 0 || value > 59) - throw Iex::ArgExc ("Cannot set frame field in time code. " - "New value is out of range."); + throw IEX_NAMESPACE::ArgExc ("Cannot set frame field in time code. " + "New value is out of range."); setBitField (_time, 0, 5, binaryToBcd (value)); } @@ -233,7 +249,7 @@ TimeCode::setFrame (int value) bool TimeCode::dropFrame () const { - return bool (bitField (_time, 6, 6)); + return !!bitField (_time, 6, 6); } @@ -247,7 +263,7 @@ TimeCode::setDropFrame (bool value) bool TimeCode::colorFrame () const { - return bool (bitField (_time, 7, 7)); + return !!bitField (_time, 7, 7); } @@ -261,7 +277,7 @@ TimeCode::setColorFrame (bool value) bool TimeCode::fieldPhase () const { - return bool (bitField (_time, 15, 15)); + return !!bitField (_time, 15, 15); } @@ -275,7 +291,7 @@ TimeCode::setFieldPhase (bool value) bool TimeCode::bgf0 () const { - return bool (bitField (_time, 23, 23)); + return !!bitField (_time, 23, 23); } @@ -289,7 +305,7 @@ TimeCode::setBgf0 (bool value) bool TimeCode::bgf1 () const { - return bool (bitField (_time, 30, 30)); + return!!bitField (_time, 30, 30); } @@ -303,7 +319,7 @@ TimeCode::setBgf1 (bool value) bool TimeCode::bgf2 () const { - return bool (bitField (_time, 31, 31)); + return !!bitField (_time, 31, 31); } @@ -318,8 +334,8 @@ int TimeCode::binaryGroup (int group) const { if (group < 1 || group > 8) - throw Iex::ArgExc ("Cannot extract binary group from time code " - "user data. Group number is out of range."); + throw IEX_NAMESPACE::ArgExc ("Cannot extract binary group from time code " + "user data. Group number is out of range."); int minBit = 4 * (group - 1); int maxBit = minBit + 3; @@ -331,8 +347,8 @@ void TimeCode::setBinaryGroup (int group, int value) { if (group < 1 || group > 8) - throw Iex::ArgExc ("Cannot extract binary group from time code " - "user data. Group number is out of range."); + throw IEX_NAMESPACE::ArgExc ("Cannot extract binary group from time code " + "user data. Group number is out of range."); int minBit = 4 * (group - 1); int maxBit = minBit + 3; @@ -345,24 +361,24 @@ TimeCode::timeAndFlags (Packing packing) const { if (packing == TV50_PACKING) { - unsigned int t = _time; + unsigned int t = _time; - t &= ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31)); + t &= ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31)); - t |= ((unsigned int) bgf0() << 15); - t |= ((unsigned int) bgf2() << 23); - t |= ((unsigned int) bgf1() << 30); - t |= ((unsigned int) fieldPhase() << 31); + t |= ((unsigned int) bgf0() << 15); + t |= ((unsigned int) bgf2() << 23); + t |= ((unsigned int) bgf1() << 30); + t |= ((unsigned int) fieldPhase() << 31); - return t; + return t; } if (packing == FILM24_PACKING) { - return _time & ~((1 << 6) | (1 << 7)); + return _time & ~((1 << 6) | (1 << 7)); } else // packing == TV60_PACKING { - return _time; + return _time; } } @@ -372,28 +388,28 @@ TimeCode::setTimeAndFlags (unsigned int value, Packing packing) { if (packing == TV50_PACKING) { - _time = value & - ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31)); + _time = value & + ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31)); - if (value & (1 << 15)) - setBgf0 (true); + if (value & (1 << 15)) + setBgf0 (true); - if (value & (1 << 23)) - setBgf2 (true); + if (value & (1 << 23)) + setBgf2 (true); - if (value & (1 << 30)) - setBgf1 (true); + if (value & (1 << 30)) + setBgf1 (true); - if (value & (1 << 31)) - setFieldPhase (true); + if (value & (1 << 31)) + setFieldPhase (true); } else if (packing == FILM24_PACKING) { - _time = value & ~((1 << 6) | (1 << 7)); + _time = value & ~((1 << 6) | (1 << 7)); } else // packing == TV60_PACKING { - _time = value; + _time = value; } } @@ -412,4 +428,4 @@ TimeCode::setUserData (unsigned int value) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTimeCode.h b/3rdparty/openexr/IlmImf/ImfTimeCode.h index 1f3ce8a4f0..1e3a46475e 100644 --- a/3rdparty/openexr/IlmImf/ImfTimeCode.h +++ b/3rdparty/openexr/IlmImf/ImfTimeCode.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -36,10 +36,13 @@ #ifndef INCLUDED_IMF_TIME_CODE_H #define INCLUDED_IMF_TIME_CODE_H +#include "ImfExport.h" +#include "ImfNamespace.h" + //----------------------------------------------------------------------------- // // class TimeCode -// +// // A TimeCode object stores time and control codes as described // in SMPTE standard 12M-1999. A TimeCode object contains the // following fields: @@ -110,9 +113,9 @@ // //----------------------------------------------------------------------------- -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + class TimeCode { public: @@ -123,9 +126,9 @@ class TimeCode enum Packing { - TV60_PACKING, // packing for 60-field television - TV50_PACKING, // packing for 50-field television - FILM24_PACKING // packing for 24-frame film + TV60_PACKING, // packing for 60-field television + TV50_PACKING, // packing for 50-field television + FILM24_PACKING // packing for 24-frame film }; @@ -133,33 +136,38 @@ class TimeCode // Constructors and assignment operator //------------------------------------- + IMF_EXPORT TimeCode (); // all fields set to 0 or false + IMF_EXPORT TimeCode (int hours, - int minutes, - int seconds, - int frame, - bool dropFrame = false, - bool colorFrame = false, - bool fieldPhase = false, - bool bgf0 = false, - bool bgf1 = false, - bool bgf2 = false, - int binaryGroup1 = 0, - int binaryGroup2 = 0, - int binaryGroup3 = 0, - int binaryGroup4 = 0, - int binaryGroup5 = 0, - int binaryGroup6 = 0, - int binaryGroup7 = 0, - int binaryGroup8 = 0); - + int minutes, + int seconds, + int frame, + bool dropFrame = false, + bool colorFrame = false, + bool fieldPhase = false, + bool bgf0 = false, + bool bgf1 = false, + bool bgf2 = false, + int binaryGroup1 = 0, + int binaryGroup2 = 0, + int binaryGroup3 = 0, + int binaryGroup4 = 0, + int binaryGroup5 = 0, + int binaryGroup6 = 0, + int binaryGroup7 = 0, + int binaryGroup8 = 0); + + IMF_EXPORT TimeCode (unsigned int timeAndFlags, - unsigned int userData = 0, - Packing packing = TV60_PACKING); + unsigned int userData = 0, + Packing packing = TV60_PACKING); + IMF_EXPORT TimeCode (const TimeCode &other); + IMF_EXPORT TimeCode & operator = (const TimeCode &other); @@ -167,53 +175,89 @@ class TimeCode // Access to individual fields //---------------------------- + IMF_EXPORT int hours () const; + IMF_EXPORT void setHours (int value); + IMF_EXPORT int minutes () const; + IMF_EXPORT void setMinutes (int value); + IMF_EXPORT int seconds () const; + IMF_EXPORT void setSeconds (int value); + IMF_EXPORT int frame () const; + IMF_EXPORT void setFrame (int value); + IMF_EXPORT bool dropFrame () const; + IMF_EXPORT void setDropFrame (bool value); + IMF_EXPORT bool colorFrame () const; + IMF_EXPORT void setColorFrame (bool value); + IMF_EXPORT bool fieldPhase () const; + IMF_EXPORT void setFieldPhase (bool value); + IMF_EXPORT bool bgf0 () const; + IMF_EXPORT void setBgf0 (bool value); + IMF_EXPORT bool bgf1 () const; + IMF_EXPORT void setBgf1 (bool value); + IMF_EXPORT bool bgf2 () const; + IMF_EXPORT void setBgf2 (bool value); + IMF_EXPORT int binaryGroup (int group) const; // group must be between 1 and 8 + IMF_EXPORT void setBinaryGroup (int group, int value); - + //--------------------------------- // Access to packed representations //--------------------------------- + IMF_EXPORT unsigned int timeAndFlags (Packing packing = TV60_PACKING) const; + IMF_EXPORT void setTimeAndFlags (unsigned int value, - Packing packing = TV60_PACKING); + Packing packing = TV60_PACKING); + IMF_EXPORT unsigned int userData () const; + IMF_EXPORT void setUserData (unsigned int value); - + + + //--------- + // Equality + //--------- + + IMF_EXPORT + bool operator == (const TimeCode &v) const; + IMF_EXPORT + bool operator != (const TimeCode &v) const; + private: unsigned int _time; @@ -221,6 +265,11 @@ class TimeCode }; -} // namespace Imf + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfTimeCodeAttribute.cpp b/3rdparty/openexr/IlmImf/ImfTimeCodeAttribute.cpp index b65e74156b..5e7ea5942a 100644 --- a/3rdparty/openexr/IlmImf/ImfTimeCodeAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfTimeCodeAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,8 +41,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -54,7 +55,7 @@ TimeCodeAttribute::staticTypeName () template <> void -TimeCodeAttribute::writeValueTo (OStream &os, int) const +TimeCodeAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.timeAndFlags()); Xdr::write (os, _value.userData()); @@ -63,7 +64,7 @@ TimeCodeAttribute::writeValueTo (OStream &os, int) const template <> void -TimeCodeAttribute::readValueFrom (IStream &is, int, int) +TimeCodeAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { unsigned int tmp; @@ -75,4 +76,4 @@ TimeCodeAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfTimeCodeAttribute.h b/3rdparty/openexr/IlmImf/ImfTimeCodeAttribute.h index 9cd19768f7..ccd893a419 100644 --- a/3rdparty/openexr/IlmImf/ImfTimeCodeAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfTimeCodeAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,30 +43,32 @@ // //----------------------------------------------------------------------------- -#include -#include - +#include "ImfAttribute.h" +#include "ImfTimeCode.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -typedef TypedAttribute TimeCodeAttribute; +typedef TypedAttribute TimeCodeAttribute; template <> +IMF_EXPORT const char *TimeCodeAttribute::staticTypeName (); template <> -void TimeCodeAttribute::writeValueTo (OStream &, int) const; +IMF_EXPORT +void TimeCodeAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, + int) const; template <> -void TimeCodeAttribute::readValueFrom (IStream &, int, int); +IMF_EXPORT +void TimeCodeAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, + int, int); + + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imf -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include -#endif #endif diff --git a/3rdparty/openexr/IlmImf/ImfVecAttribute.cpp b/3rdparty/openexr/IlmImf/ImfVecAttribute.cpp index 63f00171ec..7d51904dfb 100644 --- a/3rdparty/openexr/IlmImf/ImfVecAttribute.cpp +++ b/3rdparty/openexr/IlmImf/ImfVecAttribute.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -48,8 +48,9 @@ #include -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER +using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; template <> const char * @@ -61,7 +62,7 @@ V2iAttribute::staticTypeName () template <> void -V2iAttribute::writeValueTo (OStream &os, int) const +V2iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.x); Xdr::write (os, _value.y); @@ -70,7 +71,7 @@ V2iAttribute::writeValueTo (OStream &os, int) const template <> void -V2iAttribute::readValueFrom (IStream &is, int, int) +V2iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.x); Xdr::read (is, _value.y); @@ -87,7 +88,7 @@ V2fAttribute::staticTypeName () template <> void -V2fAttribute::writeValueTo (OStream &os, int) const +V2fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.x); Xdr::write (os, _value.y); @@ -96,7 +97,7 @@ V2fAttribute::writeValueTo (OStream &os, int) const template <> void -V2fAttribute::readValueFrom (IStream &is, int, int) +V2fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.x); Xdr::read (is, _value.y); @@ -113,7 +114,7 @@ V2dAttribute::staticTypeName () template <> void -V2dAttribute::writeValueTo (OStream &os, int) const +V2dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.x); Xdr::write (os, _value.y); @@ -122,7 +123,7 @@ V2dAttribute::writeValueTo (OStream &os, int) const template <> void -V2dAttribute::readValueFrom (IStream &is, int, int) +V2dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.x); Xdr::read (is, _value.y); @@ -139,7 +140,7 @@ V3iAttribute::staticTypeName () template <> void -V3iAttribute::writeValueTo (OStream &os, int) const +V3iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.x); Xdr::write (os, _value.y); @@ -149,7 +150,7 @@ V3iAttribute::writeValueTo (OStream &os, int) const template <> void -V3iAttribute::readValueFrom (IStream &is, int, int) +V3iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.x); Xdr::read (is, _value.y); @@ -167,7 +168,7 @@ V3fAttribute::staticTypeName () template <> void -V3fAttribute::writeValueTo (OStream &os, int) const +V3fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.x); Xdr::write (os, _value.y); @@ -177,7 +178,7 @@ V3fAttribute::writeValueTo (OStream &os, int) const template <> void -V3fAttribute::readValueFrom (IStream &is, int, int) +V3fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.x); Xdr::read (is, _value.y); @@ -195,7 +196,7 @@ V3dAttribute::staticTypeName () template <> void -V3dAttribute::writeValueTo (OStream &os, int) const +V3dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, int version) const { Xdr::write (os, _value.x); Xdr::write (os, _value.y); @@ -205,7 +206,7 @@ V3dAttribute::writeValueTo (OStream &os, int) const template <> void -V3dAttribute::readValueFrom (IStream &is, int, int) +V3dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int size, int version) { Xdr::read (is, _value.x); Xdr::read (is, _value.y); @@ -213,4 +214,4 @@ V3dAttribute::readValueFrom (IStream &is, int, int) } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfVecAttribute.h b/3rdparty/openexr/IlmImf/ImfVecAttribute.h index 83e3c8411c..8480fe6577 100644 --- a/3rdparty/openexr/IlmImf/ImfVecAttribute.h +++ b/3rdparty/openexr/IlmImf/ImfVecAttribute.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -48,54 +48,53 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfAttribute.h" #include "ImathVec.h" +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -namespace Imf { +typedef TypedAttribute V2iAttribute; +template <> IMF_EXPORT const char *V2iAttribute::staticTypeName (); +template <> IMF_EXPORT void V2iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V2iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute V2iAttribute; -template <> const char *V2iAttribute::staticTypeName (); -template <> void V2iAttribute::writeValueTo (OStream &, int) const; -template <> void V2iAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute V2fAttribute; +template <> IMF_EXPORT const char *V2fAttribute::staticTypeName (); +template <> IMF_EXPORT void V2fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V2fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute V2fAttribute; -template <> const char *V2fAttribute::staticTypeName (); -template <> void V2fAttribute::writeValueTo (OStream &, int) const; -template <> void V2fAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute V2dAttribute; +template <> IMF_EXPORT const char *V2dAttribute::staticTypeName (); +template <> IMF_EXPORT void V2dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V2dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute V2dAttribute; -template <> const char *V2dAttribute::staticTypeName (); -template <> void V2dAttribute::writeValueTo (OStream &, int) const; -template <> void V2dAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute V3iAttribute; +template <> IMF_EXPORT const char *V3iAttribute::staticTypeName (); +template <> IMF_EXPORT void V3iAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V3iAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute V3iAttribute; -template <> const char *V3iAttribute::staticTypeName (); -template <> void V3iAttribute::writeValueTo (OStream &, int) const; -template <> void V3iAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute V3fAttribute; +template <> IMF_EXPORT const char *V3fAttribute::staticTypeName (); +template <> IMF_EXPORT void V3fAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V3fAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute V3fAttribute; -template <> const char *V3fAttribute::staticTypeName (); -template <> void V3fAttribute::writeValueTo (OStream &, int) const; -template <> void V3fAttribute::readValueFrom (IStream &, int, int); +typedef TypedAttribute V3dAttribute; +template <> IMF_EXPORT const char *V3dAttribute::staticTypeName (); +template <> IMF_EXPORT void V3dAttribute::writeValueTo (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &, int) const; +template <> IMF_EXPORT void V3dAttribute::readValueFrom (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &, int, int); -typedef TypedAttribute V3dAttribute; -template <> const char *V3dAttribute::staticTypeName (); -template <> void V3dAttribute::writeValueTo (OStream &, int) const; -template <> void V3dAttribute::readValueFrom (IStream &, int, int); +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imf +#if defined (OPENEXR_IMF_INTERNAL_NAMESPACE_AUTO_EXPOSE) +namespace Imf { using namespace OPENEXR_IMF_INTERNAL_NAMESPACE; } -// Metrowerks compiler wants the .cpp file inlined, too -#ifdef __MWERKS__ -#include #endif #endif diff --git a/3rdparty/openexr/IlmImf/ImfVersion.cpp b/3rdparty/openexr/IlmImf/ImfVersion.cpp index 665cfb9276..4f49aa02cb 100644 --- a/3rdparty/openexr/IlmImf/ImfVersion.cpp +++ b/3rdparty/openexr/IlmImf/ImfVersion.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,19 +41,20 @@ #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER bool isImfMagic (const char bytes[4]) { return bytes[0] == ((MAGIC >> 0) & 0x00ff) && - bytes[1] == ((MAGIC >> 8) & 0x00ff) && - bytes[2] == ((MAGIC >> 16) & 0x00ff) && - bytes[3] == ((MAGIC >> 24) & 0x00ff); + bytes[1] == ((MAGIC >> 8) & 0x00ff) && + bytes[2] == ((MAGIC >> 16) & 0x00ff) && + bytes[3] == ((MAGIC >> 24) & 0x00ff); } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfVersion.h b/3rdparty/openexr/IlmImf/ImfVersion.h index 946e6972a5..64de7f41b1 100644 --- a/3rdparty/openexr/IlmImf/ImfVersion.h +++ b/3rdparty/openexr/IlmImf/ImfVersion.h @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,9 +42,10 @@ // //----------------------------------------------------------------------------- +#include "ImfExport.h" +#include "ImfNamespace.h" -namespace Imf { - +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER // // The MAGIC number is stored in the first four bytes of every @@ -88,11 +89,19 @@ const int LONG_NAMES_FLAG = 0x00000400; // File contains long // attribute or channel // names +const int NON_IMAGE_FLAG = 0x00000800; // File has at least one part + // which is not a regular + // scanline image or regular tiled image + // (that is, it is a deep format) + +const int MULTI_PART_FILE_FLAG = 0x00001000; // File has multiple parts + // // Bitwise OR of all known flags. // -const int ALL_FLAGS = TILED_FLAG | LONG_NAMES_FLAG; +const int ALL_FLAGS = TILED_FLAG | LONG_NAMES_FLAG | + NON_IMAGE_FLAG | MULTI_PART_FILE_FLAG; // @@ -100,6 +109,8 @@ const int ALL_FLAGS = TILED_FLAG | LONG_NAMES_FLAG; // inline bool isTiled (int version) {return !!(version & TILED_FLAG);} +inline bool isMultiPart (int version) {return !!(version & MULTI_PART_FILE_FLAG); } +inline bool isNonImage(int version) {return !!(version & NON_IMAGE_FLAG); } inline int makeTiled (int version) {return version | TILED_FLAG;} inline int makeNotTiled (int version) {return version & ~TILED_FLAG;} inline int getVersion (int version) {return version & VERSION_NUMBER_FIELD;} @@ -112,9 +123,14 @@ inline bool supportsFlags (int flags) {return !(flags & ~ALL_FLAGS);} // file is probably an OpenEXR image file, false if not. // +IMF_EXPORT bool isImfMagic (const char bytes[4]); -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfWav.cpp b/3rdparty/openexr/IlmImf/ImfWav.cpp index 361ba66a71..5d71d5615b 100644 --- a/3rdparty/openexr/IlmImf/ImfWav.cpp +++ b/3rdparty/openexr/IlmImf/ImfWav.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,8 +46,9 @@ #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER namespace { @@ -112,7 +113,7 @@ wenc16 (unsigned short a, unsigned short b, int d = ao - b; if (d < 0) - m = (m + M_OFFSET) & MOD_MASK; + m = (m + M_OFFSET) & MOD_MASK; d &= MOD_MASK; @@ -160,98 +161,98 @@ wav2Encode while (p2 <= n) { - unsigned short *py = in; - unsigned short *ey = in + oy * (ny - p2); - int oy1 = oy * p; - int oy2 = oy * p2; - int ox1 = ox * p; - int ox2 = ox * p2; - unsigned short i00,i01,i10,i11; - - // - // Y loop - // - - for (; py <= ey; py += oy2) - { - unsigned short *px = py; - unsigned short *ex = py + ox * (nx - p2); - - // - // X loop - // - - for (; px <= ex; px += ox2) - { - unsigned short *p01 = px + ox1; - unsigned short *p10 = px + oy1; - unsigned short *p11 = p10 + ox1; - - // - // 2D wavelet encoding - // - - if (w14) - { - wenc14 (*px, *p01, i00, i01); - wenc14 (*p10, *p11, i10, i11); - wenc14 (i00, i10, *px, *p10); - wenc14 (i01, i11, *p01, *p11); - } - else - { - wenc16 (*px, *p01, i00, i01); - wenc16 (*p10, *p11, i10, i11); - wenc16 (i00, i10, *px, *p10); - wenc16 (i01, i11, *p01, *p11); - } - } - - // - // Encode (1D) odd column (still in Y loop) - // - - if (nx & p) - { - unsigned short *p10 = px + oy1; - - if (w14) - wenc14 (*px, *p10, i00, *p10); - else - wenc16 (*px, *p10, i00, *p10); - - *px= i00; - } - } - - // - // Encode (1D) odd line (must loop in X) - // - - if (ny & p) - { - unsigned short *px = py; - unsigned short *ex = py + ox * (nx - p2); - - for (; px <= ex; px += ox2) - { - unsigned short *p01 = px + ox1; - - if (w14) - wenc14 (*px, *p01, i00, *p01); - else - wenc16 (*px, *p01, i00, *p01); - - *px= i00; - } - } - - // - // Next level - // - - p = p2; - p2 <<= 1; + unsigned short *py = in; + unsigned short *ey = in + oy * (ny - p2); + int oy1 = oy * p; + int oy2 = oy * p2; + int ox1 = ox * p; + int ox2 = ox * p2; + unsigned short i00,i01,i10,i11; + + // + // Y loop + // + + for (; py <= ey; py += oy2) + { + unsigned short *px = py; + unsigned short *ex = py + ox * (nx - p2); + + // + // X loop + // + + for (; px <= ex; px += ox2) + { + unsigned short *p01 = px + ox1; + unsigned short *p10 = px + oy1; + unsigned short *p11 = p10 + ox1; + + // + // 2D wavelet encoding + // + + if (w14) + { + wenc14 (*px, *p01, i00, i01); + wenc14 (*p10, *p11, i10, i11); + wenc14 (i00, i10, *px, *p10); + wenc14 (i01, i11, *p01, *p11); + } + else + { + wenc16 (*px, *p01, i00, i01); + wenc16 (*p10, *p11, i10, i11); + wenc16 (i00, i10, *px, *p10); + wenc16 (i01, i11, *p01, *p11); + } + } + + // + // Encode (1D) odd column (still in Y loop) + // + + if (nx & p) + { + unsigned short *p10 = px + oy1; + + if (w14) + wenc14 (*px, *p10, i00, *p10); + else + wenc16 (*px, *p10, i00, *p10); + + *px= i00; + } + } + + // + // Encode (1D) odd line (must loop in X) + // + + if (ny & p) + { + unsigned short *px = py; + unsigned short *ex = py + ox * (nx - p2); + + for (; px <= ex; px += ox2) + { + unsigned short *p01 = px + ox1; + + if (w14) + wenc14 (*px, *p01, i00, *p01); + else + wenc16 (*px, *p01, i00, *p01); + + *px= i00; + } + } + + // + // Next level + // + + p = p2; + p2 <<= 1; } } @@ -279,7 +280,7 @@ wav2Decode // while (p <= n) - p <<= 1; + p <<= 1; p >>= 1; p2 = p; @@ -291,100 +292,100 @@ wav2Decode while (p >= 1) { - unsigned short *py = in; - unsigned short *ey = in + oy * (ny - p2); - int oy1 = oy * p; - int oy2 = oy * p2; - int ox1 = ox * p; - int ox2 = ox * p2; - unsigned short i00,i01,i10,i11; - - // - // Y loop - // - - for (; py <= ey; py += oy2) - { - unsigned short *px = py; - unsigned short *ex = py + ox * (nx - p2); - - // - // X loop - // - - for (; px <= ex; px += ox2) - { - unsigned short *p01 = px + ox1; - unsigned short *p10 = px + oy1; - unsigned short *p11 = p10 + ox1; - - // - // 2D wavelet decoding - // - - if (w14) - { - wdec14 (*px, *p10, i00, i10); - wdec14 (*p01, *p11, i01, i11); - wdec14 (i00, i01, *px, *p01); - wdec14 (i10, i11, *p10, *p11); - } - else - { - wdec16 (*px, *p10, i00, i10); - wdec16 (*p01, *p11, i01, i11); - wdec16 (i00, i01, *px, *p01); - wdec16 (i10, i11, *p10, *p11); - } - } - - // - // Decode (1D) odd column (still in Y loop) - // - - if (nx & p) - { - unsigned short *p10 = px + oy1; - - if (w14) - wdec14 (*px, *p10, i00, *p10); - else - wdec16 (*px, *p10, i00, *p10); - - *px= i00; - } - } - - // - // Decode (1D) odd line (must loop in X) - // - - if (ny & p) - { - unsigned short *px = py; - unsigned short *ex = py + ox * (nx - p2); - - for (; px <= ex; px += ox2) - { - unsigned short *p01 = px + ox1; - - if (w14) - wdec14 (*px, *p01, i00, *p01); - else - wdec16 (*px, *p01, i00, *p01); - - *px= i00; - } - } - - // - // Next level - // - - p2 = p; - p >>= 1; + unsigned short *py = in; + unsigned short *ey = in + oy * (ny - p2); + int oy1 = oy * p; + int oy2 = oy * p2; + int ox1 = ox * p; + int ox2 = ox * p2; + unsigned short i00,i01,i10,i11; + + // + // Y loop + // + + for (; py <= ey; py += oy2) + { + unsigned short *px = py; + unsigned short *ex = py + ox * (nx - p2); + + // + // X loop + // + + for (; px <= ex; px += ox2) + { + unsigned short *p01 = px + ox1; + unsigned short *p10 = px + oy1; + unsigned short *p11 = p10 + ox1; + + // + // 2D wavelet decoding + // + + if (w14) + { + wdec14 (*px, *p10, i00, i10); + wdec14 (*p01, *p11, i01, i11); + wdec14 (i00, i01, *px, *p01); + wdec14 (i10, i11, *p10, *p11); + } + else + { + wdec16 (*px, *p10, i00, i10); + wdec16 (*p01, *p11, i01, i11); + wdec16 (i00, i01, *px, *p01); + wdec16 (i10, i11, *p10, *p11); + } + } + + // + // Decode (1D) odd column (still in Y loop) + // + + if (nx & p) + { + unsigned short *p10 = px + oy1; + + if (w14) + wdec14 (*px, *p10, i00, *p10); + else + wdec16 (*px, *p10, i00, *p10); + + *px= i00; + } + } + + // + // Decode (1D) odd line (must loop in X) + // + + if (ny & p) + { + unsigned short *px = py; + unsigned short *ex = py + ox * (nx - p2); + + for (; px <= ex; px += ox2) + { + unsigned short *p01 = px + ox1; + + if (w14) + wdec14 (*px, *p01, i00, *p01); + else + wdec16 (*px, *p01, i00, *p01); + + *px= i00; + } + } + + // + // Next level + // + + p2 = p; + p >>= 1; } } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmImf/ImfWav.h b/3rdparty/openexr/IlmImf/ImfWav.h index b84bc50a5e..97514330cd 100644 --- a/3rdparty/openexr/IlmImf/ImfWav.h +++ b/3rdparty/openexr/IlmImf/ImfWav.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,10 +42,13 @@ // 16-bit Haar Wavelet encoding and decoding // //----------------------------------------------------------------------------- +#include "ImfNamespace.h" +#include "ImfExport.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER +IMF_EXPORT void wav2Encode (unsigned short *in, // io: values in[y][x] are transformed in place @@ -55,6 +58,7 @@ wav2Encode int oy, // i : y offset unsigned short mx); // i : maximum in[x][y] value +IMF_EXPORT void wav2Decode (unsigned short *in, // io: values in[y][x] are transformed in place @@ -65,6 +69,10 @@ wav2Decode unsigned short mx); // i : maximum in[x][y] value -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/ImfXdr.h b/3rdparty/openexr/IlmImf/ImfXdr.h index 7970ca3448..0af6f67b52 100644 --- a/3rdparty/openexr/IlmImf/ImfXdr.h +++ b/3rdparty/openexr/IlmImf/ImfXdr.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -36,6 +36,7 @@ #ifndef INCLUDED_IMF_XDR_H #define INCLUDED_IMF_XDR_H + //---------------------------------------------------------------------------- // // Xdr -- routines to convert data between the machine's native @@ -56,7 +57,7 @@ // size(); returns the size, in bytes, of the // machine-independent representation // of an object of type S. -// +// // The write() and read() routines are templates; data can be written // to and read from any output or input buffer type T for which a helper // class, R, exits. Class R must define a method to store a char array @@ -102,12 +103,15 @@ // //---------------------------------------------------------------------------- -#include +#include "ImfInt64.h" #include "IexMathExc.h" #include "half.h" #include -namespace Imf { +#include "ImfNamespace.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + namespace Xdr { @@ -425,31 +429,31 @@ write (T &out, signed long v) #if LONG_MAX == 2147483647 - if (v >= 0) - { - b[4] = 0; - b[5] = 0; - b[6] = 0; - b[7] = 0; - } - else - { - b[4] = ~0; - b[5] = ~0; - b[6] = ~0; - b[7] = ~0; - } + if (v >= 0) + { + b[4] = 0; + b[5] = 0; + b[6] = 0; + b[7] = 0; + } + else + { + b[4] = ~0; + b[5] = ~0; + b[6] = ~0; + b[7] = ~0; + } #elif LONG_MAX == 9223372036854775807L - b[4] = (signed char) (v >> 32); - b[5] = (signed char) (v >> 40); - b[6] = (signed char) (v >> 48); - b[7] = (signed char) (v >> 56); + b[4] = (signed char) (v >> 32); + b[5] = (signed char) (v >> 40); + b[6] = (signed char) (v >> 48); + b[7] = (signed char) (v >> 56); #else - - #error write (T &out, signed long v) not implemented + + #error write (T &out, signed long v) not implemented #endif @@ -470,21 +474,21 @@ write (T &out, unsigned long v) #if ULONG_MAX == 4294967295U - b[4] = 0; - b[5] = 0; - b[6] = 0; - b[7] = 0; + b[4] = 0; + b[5] = 0; + b[6] = 0; + b[7] = 0; #elif ULONG_MAX == 18446744073709551615LU - b[4] = (unsigned char) (v >> 32); - b[5] = (unsigned char) (v >> 40); - b[6] = (unsigned char) (v >> 48); - b[7] = (unsigned char) (v >> 56); + b[4] = (unsigned char) (v >> 32); + b[5] = (unsigned char) (v >> 40); + b[6] = (unsigned char) (v >> 48); + b[7] = (unsigned char) (v >> 56); #else - - #error write (T &out, unsigned long v) not implemented + + #error write (T &out, unsigned long v) not implemented #endif @@ -582,8 +586,8 @@ write (T &out, const char v[]) // zero-terminated string { while (*v) { - S::writeChars (out, v, 1); - ++v; + S::writeChars (out, v, 1); + ++v; } S::writeChars (out, v, 1); @@ -596,8 +600,8 @@ pad (T &out, int n) // add n padding bytes { for (int i = 0; i < n; i++) { - const char c = 0; - S::writeChars (out, &c, 1); + const char c = 0; + S::writeChars (out, &c, 1); } } @@ -646,7 +650,7 @@ read (T &in, signed short &v) readSignedChars (in, b, 2); v = (b[0] & 0x00ff) | - (b[1] << 8); + (b[1] << 8); } @@ -659,7 +663,7 @@ read (T &in, unsigned short &v) readUnsignedChars (in, b, 2); v = (b[0] & 0x00ff) | - (b[1] << 8); + (b[1] << 8); } @@ -672,9 +676,9 @@ read (T &in, signed int &v) readSignedChars (in, b, 4); v = (b[0] & 0x000000ff) | - ((b[1] << 8) & 0x0000ff00) | - ((b[2] << 16) & 0x00ff0000) | - (b[3] << 24); + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); } @@ -687,9 +691,9 @@ read (T &in, unsigned int &v) readUnsignedChars (in, b, 4); v = (b[0] & 0x000000ff) | - ((b[1] << 8) & 0x0000ff00) | - ((b[2] << 16) & 0x00ff0000) | - (b[3] << 24); + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); } @@ -703,32 +707,32 @@ read (T &in, signed long &v) #if LONG_MAX == 2147483647 - v = (b[0] & 0x000000ff) | - ((b[1] << 8) & 0x0000ff00) | - ((b[2] << 16) & 0x00ff0000) | - (b[3] << 24); + v = (b[0] & 0x000000ff) | + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); - if (( b[4] || b[5] || b[6] || b[7]) && - (~b[4] || ~b[5] || ~b[6] || ~b[7])) - { - throw Iex::OverflowExc ("Long int overflow - read a large " - "64-bit integer in a 32-bit process."); - } + if (( b[4] || b[5] || b[6] || b[7]) && + (~b[4] || ~b[5] || ~b[6] || ~b[7])) + { + throw IEX_NAMESPACE::OverflowExc ("Long int overflow - read a large " + "64-bit integer in a 32-bit process."); + } #elif LONG_MAX == 9223372036854775807L - v = ((long) b[0] & 0x00000000000000ff) | - (((long) b[1] << 8) & 0x000000000000ff00) | - (((long) b[2] << 16) & 0x0000000000ff0000) | - (((long) b[3] << 24) & 0x00000000ff000000) | - (((long) b[4] << 32) & 0x000000ff00000000) | - (((long) b[5] << 40) & 0x0000ff0000000000) | - (((long) b[6] << 48) & 0x00ff000000000000) | - ((long) b[7] << 56); + v = ((long) b[0] & 0x00000000000000ff) | + (((long) b[1] << 8) & 0x000000000000ff00) | + (((long) b[2] << 16) & 0x0000000000ff0000) | + (((long) b[3] << 24) & 0x00000000ff000000) | + (((long) b[4] << 32) & 0x000000ff00000000) | + (((long) b[5] << 40) & 0x0000ff0000000000) | + (((long) b[6] << 48) & 0x00ff000000000000) | + ((long) b[7] << 56); #else - #error read (T &in, signed long &v) not implemented + #error read (T &in, signed long &v) not implemented #endif } @@ -744,31 +748,31 @@ read (T &in, unsigned long &v) #if ULONG_MAX == 4294967295U - v = (b[0] & 0x000000ff) | - ((b[1] << 8) & 0x0000ff00) | - ((b[2] << 16) & 0x00ff0000) | - (b[3] << 24); + v = (b[0] & 0x000000ff) | + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); - if (b[4] || b[5] || b[6] || b[7]) - { - throw Iex::OverflowExc ("Long int overflow - read a large " - "64-bit integer in a 32-bit process."); - } + if (b[4] || b[5] || b[6] || b[7]) + { + throw IEX_NAMESPACE::OverflowExc ("Long int overflow - read a large " + "64-bit integer in a 32-bit process."); + } #elif ULONG_MAX == 18446744073709551615LU - v = ((unsigned long) b[0] & 0x00000000000000ff) | - (((unsigned long) b[1] << 8) & 0x000000000000ff00) | - (((unsigned long) b[2] << 16) & 0x0000000000ff0000) | - (((unsigned long) b[3] << 24) & 0x00000000ff000000) | - (((unsigned long) b[4] << 32) & 0x000000ff00000000) | - (((unsigned long) b[5] << 40) & 0x0000ff0000000000) | - (((unsigned long) b[6] << 48) & 0x00ff000000000000) | - ((unsigned long) b[7] << 56); + v = ((unsigned long) b[0] & 0x00000000000000ff) | + (((unsigned long) b[1] << 8) & 0x000000000000ff00) | + (((unsigned long) b[2] << 16) & 0x0000000000ff0000) | + (((unsigned long) b[3] << 24) & 0x00000000ff000000) | + (((unsigned long) b[4] << 32) & 0x000000ff00000000) | + (((unsigned long) b[5] << 40) & 0x0000ff0000000000) | + (((unsigned long) b[6] << 48) & 0x00ff000000000000) | + ((unsigned long) b[7] << 56); #else - #error read (T &in, unsigned long &v) not implemented + #error read (T &in, unsigned long &v) not implemented #endif } @@ -785,13 +789,13 @@ read (T &in, unsigned long &v) readUnsignedChars (in, b, 8); v = ((Int64) b[0] & 0x00000000000000ffLL) | - (((Int64) b[1] << 8) & 0x000000000000ff00LL) | - (((Int64) b[2] << 16) & 0x0000000000ff0000LL) | - (((Int64) b[3] << 24) & 0x00000000ff000000LL) | - (((Int64) b[4] << 32) & 0x000000ff00000000LL) | - (((Int64) b[5] << 40) & 0x0000ff0000000000LL) | - (((Int64) b[6] << 48) & 0x00ff000000000000LL) | - ((Int64) b[7] << 56); + (((Int64) b[1] << 8) & 0x000000000000ff00LL) | + (((Int64) b[2] << 16) & 0x0000000000ff0000LL) | + (((Int64) b[3] << 24) & 0x00000000ff000000LL) | + (((Int64) b[4] << 32) & 0x000000ff00000000LL) | + (((Int64) b[5] << 40) & 0x0000ff0000000000LL) | + (((Int64) b[6] << 48) & 0x00ff000000000000LL) | + ((Int64) b[7] << 56); } #endif @@ -808,9 +812,9 @@ read (T &in, float &v) union {unsigned int i; float f;} u; u.i = (b[0] & 0x000000ff) | - ((b[1] << 8) & 0x0000ff00) | - ((b[2] << 16) & 0x00ff0000) | - (b[3] << 24); + ((b[1] << 8) & 0x0000ff00) | + ((b[2] << 16) & 0x00ff0000) | + (b[3] << 24); v = u.f; } @@ -827,13 +831,13 @@ read (T &in, double &v) union {Int64 i; double d;} u; u.i = ((Int64) b[0] & 0x00000000000000ffULL) | - (((Int64) b[1] << 8) & 0x000000000000ff00ULL) | - (((Int64) b[2] << 16) & 0x0000000000ff0000ULL) | - (((Int64) b[3] << 24) & 0x00000000ff000000ULL) | - (((Int64) b[4] << 32) & 0x000000ff00000000ULL) | - (((Int64) b[5] << 40) & 0x0000ff0000000000ULL) | - (((Int64) b[6] << 48) & 0x00ff000000000000ULL) | - ((Int64) b[7] << 56); + (((Int64) b[1] << 8) & 0x000000000000ff00ULL) | + (((Int64) b[2] << 16) & 0x0000000000ff0000ULL) | + (((Int64) b[3] << 24) & 0x00000000ff000000ULL) | + (((Int64) b[4] << 32) & 0x000000ff00000000ULL) | + (((Int64) b[5] << 40) & 0x0000ff0000000000ULL) | + (((Int64) b[6] << 48) & 0x00ff000000000000ULL) | + ((Int64) b[7] << 56); v = u.d; } @@ -865,13 +869,13 @@ read (T &in, int n, char v[]) // zero-terminated string { while (n >= 0) { - S::readChars (in, v, 1); + S::readChars (in, v, 1); - if (*v == 0) - break; + if (*v == 0) + break; - --n; - ++v; + --n; + ++v; } } @@ -884,14 +888,14 @@ skip (T &in, int n) // skip n padding bytes while (n >= (int) sizeof (c)) { - if (!S::readChars (in, c, sizeof (c))) - return; + if (!S::readChars (in, c, sizeof (c))) + return; - n -= sizeof (c); + n -= sizeof (c); } if (n >= 1) - S::readChars (in, c, n); + S::readChars (in, c, n); } @@ -905,12 +909,19 @@ template <> inline int size () {return 4;} template <> inline int size () {return 4;} template <> inline int size () {return 8;} template <> inline int size () {return 8;} +template <> inline int size () {return 8;} template <> inline int size () {return 4;} template <> inline int size () {return 8;} template <> inline int size () {return 2;} } // namespace Xdr -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + +#if defined (OPENEXR_IMF_INTERNAL_NAMESPACE_AUTO_EXPOSE) +namespace Imf{using namespace OPENEXR_IMF_INTERNAL_NAMESPACE;} +#endif + #endif diff --git a/3rdparty/openexr/IlmImf/ImfZip.cpp b/3rdparty/openexr/IlmImf/ImfZip.cpp new file mode 100644 index 0000000000..4e6a62fb7f --- /dev/null +++ b/3rdparty/openexr/IlmImf/ImfZip.cpp @@ -0,0 +1,305 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImfZip.h" +#include "ImfCheckedArithmetic.h" +#include "ImfNamespace.h" +#include "ImfSimd.h" +#include "Iex.h" + +#include +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +Zip::Zip(size_t maxRawSize): + _maxRawSize(maxRawSize), + _tmpBuffer(0) +{ + _tmpBuffer = new char[_maxRawSize]; +} + +Zip::Zip(size_t maxScanLineSize, size_t numScanLines): + _maxRawSize(0), + _tmpBuffer(0) +{ + _maxRawSize = uiMult (maxScanLineSize, numScanLines); + _tmpBuffer = new char[_maxRawSize]; +} + +Zip::~Zip() +{ + if (_tmpBuffer) delete[] _tmpBuffer; +} + +size_t +Zip::maxRawSize() +{ + return _maxRawSize; +} + +size_t +Zip::maxCompressedSize() +{ + return uiAdd (uiAdd (_maxRawSize, + size_t (ceil (_maxRawSize * 0.01))), + size_t (100)); +} + +int +Zip::compress(const char *raw, int rawSize, char *compressed) +{ + // + // Reorder the pixel data. + // + + { + char *t1 = _tmpBuffer; + char *t2 = _tmpBuffer + (rawSize + 1) / 2; + const char *stop = raw + rawSize; + + while (true) + { + if (raw < stop) + *(t1++) = *(raw++); + else + break; + + if (raw < stop) + *(t2++) = *(raw++); + else + break; + } + } + + // + // Predictor. + // + + { + unsigned char *t = (unsigned char *) _tmpBuffer + 1; + unsigned char *stop = (unsigned char *) _tmpBuffer + rawSize; + int p = t[-1]; + + while (t < stop) + { + int d = int (t[0]) - p + (128 + 256); + p = t[0]; + t[0] = d; + ++t; + } + } + + // + // Compress the data using zlib + // + + uLongf outSize = int(ceil(rawSize * 1.01)) + 100; + + if (Z_OK != ::compress ((Bytef *)compressed, &outSize, + (const Bytef *) _tmpBuffer, rawSize)) + { + throw IEX_NAMESPACE::BaseExc ("Data compression (zlib) failed."); + } + + return outSize; +} + +#ifdef IMF_HAVE_SSE4_1 + +static void +reconstruct_sse41(char *buf, size_t outSize) +{ + static const size_t bytesPerChunk = sizeof(__m128i); + const size_t vOutSize = outSize / bytesPerChunk; + + const __m128i c = _mm_set1_epi8(-128); + const __m128i shuffleMask = _mm_set1_epi8(15); + + // The first element doesn't have its high bit flipped during compression, + // so it must not be flipped here. To make the SIMD loop nice and + // uniform, we pre-flip the bit so that the loop will unflip it again. + buf[0] += -128; + + __m128i *vBuf = reinterpret_cast<__m128i *>(buf); + __m128i vPrev = _mm_setzero_si128(); + for (size_t i=0; i(source); + const __m128i *v2 = reinterpret_cast(source + (outSize + 1) / 2); + __m128i *vOut = reinterpret_cast<__m128i *>(out); + + for (size_t i=0; i(v1); + const char *t2 = reinterpret_cast(v2); + char *sOut = reinterpret_cast(vOut); + + for (size_t i=vOutSize*bytesPerChunk; i -#include +#include "ImfNamespace.h" +#include "ImfExport.h" -using namespace std; +#include -//----------------------------------------------------- -// Compute a lookup table for float-to-half conversion. -// -// When indexed with the combined sign and exponent of -// a float, the table either returns the combined sign -// and exponent of the corresponding half, or zero if -// the corresponding half may not be normalized (zero, -// denormalized, overflow). -//----------------------------------------------------- +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER -void -initELut (unsigned short eLut[]) +class Zip { - for (int i = 0; i < 0x100; i++) - { - int e = (i & 0x0ff) - (127 - 15); + public: + IMF_EXPORT + explicit Zip(size_t rawMaxSize); + IMF_EXPORT + Zip(size_t maxScanlineSize, size_t numScanLines); + IMF_EXPORT + ~Zip(); + + IMF_EXPORT + size_t maxRawSize(); + IMF_EXPORT + size_t maxCompressedSize(); - if (e <= 0 || e >= 30) - { // - // Special case + // Compress the raw data into the provided buffer. + // Returns the amount of compressed data. // + IMF_EXPORT + int compress(const char *raw, int rawSize, char *compressed); - eLut[i] = 0; - eLut[i | 0x100] = 0; - } - else - { - // - // Common case - normalized half, no exponent overflow possible + // + // Uncompress the compressed data into the provided + // buffer. Returns the amount of raw data actually decoded. // + IMF_EXPORT + int uncompress(const char *compressed, int compressedSize, + char *raw); - eLut[i] = (e << 10); - eLut[i | 0x100] = ((e << 10) | 0x8000); - } - } -} - - -//------------------------------------------------------------ -// Main - prints the sign-and-exponent conversion lookup table -//------------------------------------------------------------ - -int -main () -{ - const int tableSize = 1 << 9; - unsigned short eLut[tableSize]; - initELut (eLut); - - cout << "//\n" - "// This is an automatically generated file.\n" - "// Do not edit.\n" - "//\n\n"; - - cout << "{\n "; - - for (int i = 0; i < tableSize; i++) - { - cout << setw (5) << eLut[i] << ", "; + private: + size_t _maxRawSize; + char *_tmpBuffer; - if (i % 8 == 7) - { - cout << "\n"; + Zip(); + Zip(const Zip&); +}; - if (i < tableSize - 1) - cout << " "; - } - } +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT - cout << "};\n"; - return 0; -} +#endif diff --git a/3rdparty/openexr/IlmImf/ImfZipCompressor.cpp b/3rdparty/openexr/IlmImf/ImfZipCompressor.cpp index 9296a5f99c..b0d6989bb4 100644 --- a/3rdparty/openexr/IlmImf/ImfZipCompressor.cpp +++ b/3rdparty/openexr/IlmImf/ImfZipCompressor.cpp @@ -2,9 +2,9 @@ // // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,14 +39,14 @@ // class ZipCompressor // //----------------------------------------------------------------------------- -//#define ZLIB_WINAPI -#include -#include +#include "ImfZipCompressor.h" +#include "ImfCheckedArithmetic.h" #include "Iex.h" #include +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER ZipCompressor::ZipCompressor @@ -57,28 +57,15 @@ ZipCompressor::ZipCompressor Compressor (hdr), _maxScanLineSize (maxScanLineSize), _numScanLines (numScanLines), - _tmpBuffer (0), - _outBuffer (0) + _outBuffer (0), + _zip(maxScanLineSize, numScanLines) { - size_t maxInBytes = - uiMult (maxScanLineSize, numScanLines); - - size_t maxOutBytes = - uiAdd (uiAdd (maxInBytes, - size_t (ceil (maxInBytes * 0.01))), - size_t (100)); - - _tmpBuffer = - new char [maxInBytes]; - - _outBuffer = - new char [maxOutBytes]; + _outBuffer = new char[_zip.maxCompressedSize()]; } ZipCompressor::~ZipCompressor () { - delete [] _tmpBuffer; delete [] _outBuffer; } @@ -92,72 +79,21 @@ ZipCompressor::numScanLines () const int ZipCompressor::compress (const char *inPtr, - int inSize, - int /*minY*/, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { // - // Special case ­- empty input buffer + // Special case ďż˝- empty input buffer // if (inSize == 0) { - outPtr = _outBuffer; - return 0; + outPtr = _outBuffer; + return 0; } - // - // Reorder the pixel data. - // - - { - char *t1 = _tmpBuffer; - char *t2 = _tmpBuffer + (inSize + 1) / 2; - const char *stop = inPtr + inSize; - - while (true) - { - if (inPtr < stop) - *(t1++) = *(inPtr++); - else - break; - - if (inPtr < stop) - *(t2++) = *(inPtr++); - else - break; - } - } - - // - // Predictor. - // - - { - unsigned char *t = (unsigned char *) _tmpBuffer + 1; - unsigned char *stop = (unsigned char *) _tmpBuffer + inSize; - int p = t[-1]; - - while (t < stop) - { - int d = int (t[0]) - p + (128 + 256); - p = t[0]; - t[0] = d; - ++t; - } - } - - // - // Compress the data using zlib - // - - uLongf outSize = int(ceil(inSize * 1.01)) + 100; - - if (Z_OK != ::compress ((Bytef *)_outBuffer, &outSize, - (const Bytef *) _tmpBuffer, inSize)) - { - throw Iex::BaseExc ("Data compression (zlib) failed."); - } + int outSize = _zip.compress(inPtr, inSize, _outBuffer); outPtr = _outBuffer; return outSize; @@ -166,75 +102,26 @@ ZipCompressor::compress (const char *inPtr, int ZipCompressor::uncompress (const char *inPtr, - int inSize, - int /*minY*/, - const char *&outPtr) + int inSize, + int minY, + const char *&outPtr) { // - // Special case ­- empty input buffer + // Special case ďż˝- empty input buffer // if (inSize == 0) { - outPtr = _outBuffer; - return 0; - } - - // - // Decompress the data using zlib - // - - uLongf outSize = _maxScanLineSize * _numScanLines; - - if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer, &outSize, - (const Bytef *) inPtr, inSize)) - { - throw Iex::InputExc ("Data decompression (zlib) failed."); - } - - // - // Predictor. - // - - { - unsigned char *t = (unsigned char *) _tmpBuffer + 1; - unsigned char *stop = (unsigned char *) _tmpBuffer + outSize; - - while (t < stop) - { - int d = int (t[-1]) + int (t[0]) - 128; - t[0] = d; - ++t; + outPtr = _outBuffer; + return 0; } - } - - // - // Reorder the pixel data. - // - { - const char *t1 = _tmpBuffer; - const char *t2 = _tmpBuffer + (outSize + 1) / 2; - char *s = _outBuffer; - char *stop = s + outSize; - - while (true) - { - if (s < stop) - *(s++) = *(t1++); - else - break; - - if (s < stop) - *(s++) = *(t2++); - else - break; - } - } + int outSize = _zip.uncompress(inPtr, inSize, _outBuffer); outPtr = _outBuffer; return outSize; } -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT + diff --git a/3rdparty/openexr/IlmImf/ImfZipCompressor.h b/3rdparty/openexr/IlmImf/ImfZipCompressor.h index ae1f988512..6744b63261 100644 --- a/3rdparty/openexr/IlmImf/ImfZipCompressor.h +++ b/3rdparty/openexr/IlmImf/ImfZipCompressor.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,41 +43,52 @@ // //----------------------------------------------------------------------------- -#include +#include "ImfCompressor.h" +#include "ImfZip.h" +#include "ImfNamespace.h" -namespace Imf { +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class ZipCompressor: public Compressor { public: - ZipCompressor (const Header &hdr, + IMF_EXPORT + ZipCompressor (const Header &hdr, size_t maxScanLineSize, size_t numScanLines); + IMF_EXPORT virtual ~ZipCompressor (); + IMF_EXPORT virtual int numScanLines () const; + IMF_EXPORT virtual int compress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); + int inSize, + int minY, + const char *&outPtr); + IMF_EXPORT virtual int uncompress (const char *inPtr, - int inSize, - int minY, - const char *&outPtr); + int inSize, + int minY, + const char *&outPtr); private: int _maxScanLineSize; int _numScanLines; - char * _tmpBuffer; char * _outBuffer; + Zip _zip; }; -} // namespace Imf +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT + + + + #endif diff --git a/3rdparty/openexr/IlmImf/dwaLookups.cpp b/3rdparty/openexr/IlmImf/dwaLookups.cpp new file mode 100644 index 0000000000..ac5ac099bc --- /dev/null +++ b/3rdparty/openexr/IlmImf/dwaLookups.cpp @@ -0,0 +1,650 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2009-2014 DreamWorks Animation LLC. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of DreamWorks Animation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#define OPENEXR_BUILTIN_TABLES + +// +// A program to generate various acceleration lookup tables +// for Imf::DwaCompressor +// + +#include +#include +#include +#include +#include + +#include + +#ifndef OPENEXR_BUILTIN_TABLES +#ifdef OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN +#include +#endif +#endif // OPENEXR_BUILTIN_TABLES + +#include +#include +#include +#include +#include +#include "ImfNamespace.h" + +using namespace OPENEXR_IMF_NAMESPACE; + +namespace { + +#ifdef OPENEXR_BUILTIN_TABLES +static unsigned short dwaCompressorNoOp[0x10000] = {}; +static unsigned short dwaCompressorToLinear[0x10000] = {}; +static unsigned short dwaCompressorToNonlinear[0x10000] = {}; + +//static unsigned int closestDataOffset[0x10000] = {}; +//static unsigned short closestData[0x80000] = {}; +#else + + class LutHeaderWorker + { + public: + class Runner : public ILMTHREAD_NAMESPACE::Thread + { + public: + Runner(LutHeaderWorker &worker, bool output): + ILMTHREAD_NAMESPACE::Thread(), + _worker(worker), + _output(output) + { + start(); + } + + virtual ~Runner() + { + _semaphore.wait(); + } + + virtual void run() + { + _semaphore.post(); + _worker.run(_output); + } + + private: + LutHeaderWorker &_worker; + bool _output; + ILMTHREAD_NAMESPACE::Semaphore _semaphore; + + }; // class LutHeaderWorker::Runner + + + LutHeaderWorker(size_t startValue, + size_t endValue): + _lastCandidateCount(0), + _startValue(startValue), + _endValue(endValue), + _numElements(0), + _offset(new size_t[numValues()]), + _elements(new unsigned short[1024*1024*2]) + { + } + + ~LutHeaderWorker() + { + delete[] _offset; + delete[] _elements; + } + + size_t lastCandidateCount() const + { + return _lastCandidateCount; + } + + size_t numValues() const + { + return _endValue - _startValue; + } + + size_t numElements() const + { + return _numElements; + } + + const size_t* offset() const + { + return _offset; + } + + const unsigned short* elements() const + { + return _elements; + } + + void run(bool outputProgress) + { + half candidate[16]; + int candidateCount = 0; + + for (size_t input=_startValue; input<_endValue; ++input) { + + if (outputProgress) { +#ifdef __GNUC__ + if (input % 100 == 0) { + fprintf(stderr, + " Building acceleration for DwaCompressor, %.2f %% %c", + 100.*(float)input/(float)numValues(), 13); + } +#else + if (input % 1000 == 0) { + fprintf(stderr, + " Building acceleration for DwaCompressor, %.2f %%\n", + 100.*(float)input/(float)numValues()); + } +#endif + } + + + int numSetBits = countSetBits(input); + half inputHalf, closestHalf; + + inputHalf.setBits(input); + + _offset[input - _startValue] = _numElements; + + // Gather candidates + candidateCount = 0; + for (int targetNumSetBits=numSetBits-1; targetNumSetBits>=0; + --targetNumSetBits) { + bool valueFound = false; + + for (int i=0; i<65536; ++i) { + if (countSetBits(i) != targetNumSetBits) continue; + + if (!valueFound) { + closestHalf.setBits(i); + valueFound = true; + } else { + half tmpHalf; + + tmpHalf.setBits(i); + + if (fabs((float)inputHalf - (float)tmpHalf) < + fabs((float)inputHalf - (float)closestHalf)) { + closestHalf = tmpHalf; + } + } + } + + if (valueFound == false) { + fprintf(stderr, "bork bork bork!\n"); + } + + candidate[candidateCount] = closestHalf; + candidateCount++; + } + + // Sort candidates by increasing number of bits set + for (int i=0; i> 8]; + } + + }; // class LutHeaderWorker + +#endif // OPENEXR_BUILTIN_TABLES + +} // namespace + + +// +// Generate a no-op LUT, to cut down in conditional branches +// +static void +generateNoop() +{ +#ifndef OPENEXR_BUILTIN_TABLES + printf("const unsigned short dwaCompressorNoOp[] = \n"); + printf("{"); +#endif // OPENEXR_BUILTIN_TABLES + for (int i=0; i<65536; ++i) { +#ifndef OPENEXR_BUILTIN_TABLES + if (i % 8 == 0) { + printf("\n "); + } +#endif // OPENEXR_BUILTIN_TABLES + unsigned short dst; + char *tmp = (char *)(&dst); + + unsigned short src = (unsigned short)i; + Xdr::write (tmp, src); +#ifndef OPENEXR_BUILTIN_TABLES + printf("0x%04x, ", dst); +#else + dwaCompressorNoOp[i] = dst; +#endif // OPENEXR_BUILTIN_TABLES + } +#ifndef OPENEXR_BUILTIN_TABLES + printf("\n};\n"); +#endif // OPENEXR_BUILTIN_TABLES +} + +// +// Nonlinearly encode luminance. For values below 1.0, we want +// to use a gamma 2.2 function to match what is fairly common +// for storing output referred. However, > 1, gamma functions blow up, +// and log functions are much better behaved. We could use a log +// function everywhere, but it tends to over-sample dark +// regions and undersample the brighter regions, when +// compared to the way real devices reproduce values. +// +// So, above 1, use a log function which is a smooth blend +// into the gamma function. +// +// Nonlinear(linear) = +// +// linear^(1./2.2) / linear <= 1.0 +// | +// ln(linear)/ln(e^2.2) + 1 \ otherwise +// +// +// toNonlinear[] needs to take in XDR format half float values, +// and output NATIVE format float. +// +// toLinear[] does the opposite - takes in NATIVE half and +// outputs XDR half values. +// + +static void +generateToLinear() +{ +#ifndef OPENEXR_BUILTIN_TABLES + unsigned short toLinear[65536]; +#else + unsigned short* toLinear = dwaCompressorToLinear; +#endif // OPENEXR_BUILTIN_TABLES + + toLinear[0] = 0; + + for (int i=1; i<65536; ++i) { + half h; + float sign = 1; + float logBase = pow(2.7182818, 2.2); + + // map NaN and inf to 0 + if ((i & 0x7c00) == 0x7c00) { + toLinear[i] = 0; + continue; + } + + // + // _toLinear - assume i is NATIVE, but our output needs + // to get flipped to XDR + // + h.setBits(i); + sign = 1; + if ((float)h < 0) { + sign = -1; + } + + if ( fabs( (float)h) <= 1.0 ) { + h = (half)(sign * pow((float)fabs((float)h), 2.2f)); + } else { + h = (half)(sign * pow(logBase, (float)(fabs((float)h) - 1.0))); + } + + { + char *tmp = (char *)(&toLinear[i]); + + Xdr::write ( tmp, h.bits()); + } + } +#ifndef OPENEXR_BUILTIN_TABLES + printf("const unsigned short dwaCompressorToLinear[] = \n"); + printf("{"); + for (int i=0; i<65536; ++i) { + if (i % 8 == 0) { + printf("\n "); + } + printf("0x%04x, ", toLinear[i]); + } + printf("\n};\n"); +#endif // OPENEXR_BUILTIN_TABLES +} + + +static void +generateToNonlinear() +{ +#ifndef OPENEXR_BUILTIN_TABLES + unsigned short toNonlinear[65536]; +#else + unsigned short* toNonlinear = dwaCompressorToNonlinear; +#endif // OPENEXR_BUILTIN_TABLES + + toNonlinear[0] = 0; + + for (int i=1; i<65536; ++i) { + unsigned short usNative, usXdr; + half h; + float sign = 1; + float logBase = pow(2.7182818, 2.2); + + usXdr = i; + + { + const char *tmp = (char *)(&usXdr); + + Xdr::read(tmp, usNative); + } + + // map NaN and inf to 0 + if ((usNative & 0x7c00) == 0x7c00) { + toNonlinear[i] = 0; + continue; + } + + // + // toNonlinear - assume i is XDR + // + h.setBits(usNative); + sign = 1; + if ((float)h < 0) { + sign = -1; + } + + if ( fabs( (float)h ) <= 1.0) { + h = (half)(sign * pow(fabs((float)h), 1.f/2.2f)); + } else { + h = (half)(sign * ( log(fabs((float)h)) / log(logBase) + 1.0) ); + } + toNonlinear[i] = h.bits(); + } +#ifndef OPENEXR_BUILTIN_TABLES + printf("const unsigned short dwaCompressorToNonlinear[] = \n"); + printf("{"); + for (int i=0; i<65536; ++i) { + if (i % 8 == 0) { + printf("\n "); + } + printf("0x%04x, ", toNonlinear[i]); + } + printf("\n};\n"); +#endif // OPENEXR_BUILTIN_TABLES +} + + +#ifndef OPENEXR_BUILTIN_TABLES +// +// Attempt to get available CPUs in a somewhat portable way. +// + +int +cpuCount() +{ + if (!ILMTHREAD_NAMESPACE::supportsThreads()) return 1; + + int cpuCount = 1; + +#if defined (OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN) + + cpuCount = sysconf(_SC_NPROCESSORS_ONLN); + +#elif defined (_WIN32) + + SYSTEM_INFO sysinfo; + GetSystemInfo( &sysinfo ); + cpuCount = sysinfo.dwNumberOfProcessors; + +#endif + + if (cpuCount < 1) cpuCount = 1; + return cpuCount; +} + +// +// Generate acceleration luts for the quantization. +// +// For each possible input value, we want to find the closest numbers +// which have one fewer bits set than before. +// +// This gives us num_bits(input)-1 values per input. If we alloc +// space for everything, that's like a 2MB table. We can do better +// by compressing all the values to be contigious and using offset +// pointers. +// +// After we've found the candidates with fewer bits set, sort them +// based on increasing numbers of bits set. This way, on quantize(), +// we can scan through the list and halt once we find the first +// candidate within the error range. For small values that can +// be quantized to 0, 0 is the first value tested and the search +// can exit fairly quickly. +// + +void +generateLutHeader() +{ + std::vector workers; + + size_t numWorkers = cpuCount(); + size_t workerInterval = 65536 / numWorkers; + + for (size_t i=0; i runners; + for (size_t i=0; irun(i == 0); + } + } + + printf("static unsigned int closestDataOffset[] = {\n"); + int offsetIdx = 0; + int offsetPrev = 0; + for (size_t i=0; inumValues(); ++value) { + if (offsetIdx % 8 == 0) { + printf(" "); + } + printf("%6lu, ", workers[i]->offset()[value] + offsetPrev); + if (offsetIdx % 8 == 7) { + printf("\n"); + } + offsetIdx++; + } + offsetPrev += workers[i]->offset()[workers[i]->numValues()-1] + + workers[i]->lastCandidateCount(); + } + printf("};\n\n\n"); + + + printf("static unsigned short closestData[] = {\n"); + int elementIdx = 0; + for (size_t i=0; inumElements(); ++element) { + if (elementIdx % 8 == 0) { + printf(" "); + } + printf("%5d, ", workers[i]->elements()[element]); + if (elementIdx % 8 == 7) { + printf("\n"); + } + elementIdx++; + } + } + printf("};\n\n\n"); + + for (size_t i=0; i\n"); + printf("\n\n\n"); + + generateNoop(); + + printf("\n\n\n"); + + generateToLinear(); + + printf("\n\n\n"); + + generateToNonlinear(); + + printf("\n\n\n"); + + generateLutHeader(); + + return 0; +} +#else // OPENEXR_BUILTIN_TABLES + +#include "dwaLookups.h" + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER + +static void init_dwa_() +{ + generateNoop(); + generateToLinear(); + generateToNonlinear(); + // N/A: generateLutHeader(); +} + +static inline void init_dwa() +{ + static bool initialized = false; + if (!initialized) + { + init_dwa_(); + initialized = true; + } +} + +const unsigned short* get_dwaCompressorNoOp() +{ + init_dwa(); + return dwaCompressorNoOp; +} +const unsigned short* get_dwaCompressorToLinear() +{ + init_dwa(); + return dwaCompressorToLinear; +} +const unsigned short* get_dwaCompressorToNonlinear() +{ + init_dwa(); + return dwaCompressorToNonlinear; +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT + +#endif // OPENEXR_BUILTIN_TABLES diff --git a/3rdparty/openexr/IlmImf/dwaLookups.h b/3rdparty/openexr/IlmImf/dwaLookups.h new file mode 100644 index 0000000000..8f0da83704 --- /dev/null +++ b/3rdparty/openexr/IlmImf/dwaLookups.h @@ -0,0 +1,22 @@ +#include "ImfHeader.h" +#include "ImfNamespace.h" +#include "ImfExport.h" + +#include + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER + + +const unsigned short* get_dwaCompressorNoOp(); +const unsigned short* get_dwaCompressorToLinear(); +const unsigned short* get_dwaCompressorToNonlinear(); + +//const unsigned int* get_closestDataOffset(); +//const unsigned short* get_closestData(); +static inline +const unsigned short* get_dwaClosest(int idx) +{ + throw std::runtime_error("OpenEXR: DW* compression tables are not available"); +} + +OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT diff --git a/3rdparty/openexr/IlmThread/IlmThread.cpp b/3rdparty/openexr/IlmThread/IlmThread.cpp index ef1ace111b..45c958c28c 100644 --- a/3rdparty/openexr/IlmThread/IlmThread.cpp +++ b/3rdparty/openexr/IlmThread/IlmThread.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -34,21 +34,56 @@ //----------------------------------------------------------------------------- // -// class Thread -- dummy implementation for -// platforms that do not support threading +// class Thread -- this file contains two implementations of thread: +// - dummy implementation for platforms that do not support threading +// when OPENEXR_FORCE_CXX03 is on +// - c++11 and newer version // //----------------------------------------------------------------------------- #include "IlmBaseConfig.h" - -#if !defined (_WIN32) && !defined(_WIN64) && !(HAVE_PTHREAD) - #include "IlmThread.h" #include "Iex.h" -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER + +#ifndef ILMBASE_FORCE_CXX03 +//----------------------------------------------------------------------------- +// C++11 and newer implementation +//----------------------------------------------------------------------------- +bool +supportsThreads () +{ + return true; +} + +Thread::Thread () +{ + // empty +} + + +Thread::~Thread () +{ + // hopefully the thread has basically exited and we are just + // cleaning up, because run is a virtual function, so the v-table + // has already been partly destroyed... + if ( _thread.joinable () ) + _thread.join (); +} +void +Thread::start () +{ + _thread = std::thread (&Thread::run, this); +} + +#else +# if !defined (_WIN32) &&!(_WIN64) && !(HAVE_PTHREAD) +//----------------------------------------------------------------------------- +// OPENEXR_FORCE_CXX03 with no windows / pthread support +//----------------------------------------------------------------------------- bool supportsThreads () { @@ -58,23 +93,24 @@ supportsThreads () Thread::Thread () { - throw Iex::NoImplExc ("Threads not supported on this platform."); + throw IEX_NAMESPACE::NoImplExc ("Threads not supported on this platform."); } Thread::~Thread () { - throw Iex::NoImplExc ("Threads not supported on this platform."); + throw IEX_NAMESPACE::NoImplExc ("Threads not supported on this platform."); } void Thread::start () { - throw Iex::NoImplExc ("Threads not supported on this platform."); + throw IEX_NAMESPACE::NoImplExc ("Threads not supported on this platform."); } +# endif +#endif -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT -#endif diff --git a/3rdparty/openexr/IlmThread/IlmThread.h b/3rdparty/openexr/IlmThread/IlmThread.h index dabe61a1b5..26925aa0c5 100644 --- a/3rdparty/openexr/IlmThread/IlmThread.h +++ b/3rdparty/openexr/IlmThread/IlmThread.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -91,29 +91,25 @@ //----------------------------------------------------------------------------- #include "IlmBaseConfig.h" - -#if defined _WIN32 || defined _WIN64 - #ifdef NOMINMAX - #undef NOMINMAX - #endif - #define NOMINMAX - #include - #include -#elif HAVE_PTHREAD - #include -#endif - -#if defined(OPENEXR_DLL) && !defined(ZENO_STATIC) - #ifdef ILMTHREAD_EXPORTS - #define ILMTHREAD_EXPORT __declspec(dllexport) - #else - #define ILMTHREAD_EXPORT __declspec(dllimport) - #endif +#include "IlmThreadExport.h" +#include "IlmThreadNamespace.h" + +#ifdef ILMBASE_FORCE_CXX03 +# if defined _WIN32 || defined _WIN64 +# ifdef NOMINMAX +# undef NOMINMAX +# endif +# define NOMINMAX +# include +# include +# elif HAVE_PTHREAD +# include +# endif #else - #define ILMTHREAD_EXPORT +# include #endif -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER // // Query function to determine if the current platform supports @@ -123,29 +119,35 @@ namespace IlmThread { ILMTHREAD_EXPORT bool supportsThreads (); -class ILMTHREAD_EXPORT Thread +class Thread { public: - Thread (); - virtual ~Thread (); + ILMTHREAD_EXPORT Thread (); + ILMTHREAD_EXPORT virtual ~Thread (); - void start (); - virtual void run () = 0; + ILMTHREAD_EXPORT void start (); + ILMTHREAD_EXPORT virtual void run () = 0; private: - #if defined _WIN32 || defined _WIN64 - HANDLE _thread; - #elif HAVE_PTHREAD - pthread_t _thread; - #endif - +#ifdef ILMBASE_FORCE_CXX03 +# if defined _WIN32 || defined _WIN64 + HANDLE _thread; +# elif HAVE_PTHREAD + pthread_t _thread; +# endif void operator = (const Thread& t); // not implemented Thread (const Thread& t); // not implemented +#else + std::thread _thread; + + Thread &operator= (const Thread& t) = delete; + Thread (const Thread& t) = delete; +#endif }; -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_ILM_THREAD_H diff --git a/3rdparty/openexr/IlmThread/IlmThreadExport.h b/3rdparty/openexr/IlmThread/IlmThreadExport.h new file mode 100644 index 0000000000..96d2200fe7 --- /dev/null +++ b/3rdparty/openexr/IlmThread/IlmThreadExport.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#if defined(OPENEXR_DLL) + #if defined(ILMTHREAD_EXPORTS) + #define ILMTHREAD_EXPORT __declspec(dllexport) + #define ILMTHREAD_EXPORT_CONST extern __declspec(dllexport) + #else + #define ILMTHREAD_EXPORT __declspec(dllimport) + #define ILMTHREAD_EXPORT_CONST extern __declspec(dllimport) + #endif +#else + #define ILMTHREAD_EXPORT + #define ILMTHREAD_EXPORT_CONST extern const +#endif diff --git a/3rdparty/openexr/IlmThread/IlmThreadForward.h b/3rdparty/openexr/IlmThread/IlmThreadForward.h new file mode 100644 index 0000000000..e57d5968b0 --- /dev/null +++ b/3rdparty/openexr/IlmThread/IlmThreadForward.h @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_ILMTHREADFORWARD_H +#define INCLUDED_ILMTHREADFORWARD_H + +#include "IlmThreadNamespace.h" + +#ifndef ILMBASE_FORCE_CXX03 +namespace std { class mutex; } +#endif + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER + +class Thread; +#ifdef ILMBASE_FORCE_CXX03 +class Mutex; +#else +using Mutex = std::mutex; +#endif +class Lock; +class ThreadPool; +class Task; +class TaskGroup; +class Semaphore; + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_ILMTHREADFORWARD_H diff --git a/3rdparty/openexr/IlmThread/IlmThreadMutex.cpp b/3rdparty/openexr/IlmThread/IlmThreadMutex.cpp index 331de074dc..f056f7396e 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadMutex.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadMutex.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,11 +41,11 @@ #include "IlmBaseConfig.h" -#if !defined (_WIN32) && !(_WIN64) && !(HAVE_PTHREAD) - -#include "IlmThreadMutex.h" +#ifdef ILMBASE_FORCE_CXX03 +# if !defined (_WIN32) && !(_WIN64) && !(HAVE_PTHREAD) +# include "IlmThreadMutex.h" -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER Mutex::Mutex () {} @@ -54,6 +54,7 @@ void Mutex::lock () const {} void Mutex::unlock () const {} -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT +# endif #endif diff --git a/3rdparty/openexr/IlmThread/IlmThreadMutex.h b/3rdparty/openexr/IlmThread/IlmThreadMutex.h index df5729e7cc..97c43bce34 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadMutex.h +++ b/3rdparty/openexr/IlmThread/IlmThreadMutex.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -51,7 +51,7 @@ // share a Lock object among multiple threads. // // Typical usage: -// +// // Mutex mtx; // Create a Mutex object that is visible // //to multiple threads // @@ -66,24 +66,45 @@ // //----------------------------------------------------------------------------- +#include "IlmThreadExport.h" #include "IlmBaseConfig.h" - -#if defined _WIN32 || defined _WIN64 - #ifdef NOMINMAX - #undef NOMINMAX - #endif - #define NOMINMAX - #include -#elif HAVE_PTHREAD - #include +#include "IlmThreadNamespace.h" + +#ifdef ILMBASE_FORCE_CXX03 +# if defined _WIN32 || defined _WIN64 +# ifdef NOMINMAX +# undef NOMINMAX +# endif +# define NOMINMAX +# include +# elif HAVE_PTHREAD +# include +# endif +#else +# include #endif -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER -class Lock; +// in c++11, this can just be +// +// using Mutex = std::mutex; +// unfortunately we can't use std::unique_lock as a replacement for Lock since +// they have different API. +// +// if we decide to break the API, we can just +// +// using Lock = std::lock_guard; +// or +// using Lock = std::unique_lock; +// +// (or eliminate the type completely and have people use the std library) +#ifdef ILMBASE_FORCE_CXX03 -class Mutex +class Lock; + +class ILMTHREAD_EXPORT Mutex { public: @@ -96,25 +117,26 @@ class Mutex void unlock () const; #if defined _WIN32 || defined _WIN64 - mutable CRITICAL_SECTION _mutex; + mutable CRITICAL_SECTION _mutex; #elif HAVE_PTHREAD - mutable pthread_mutex_t _mutex; + mutable pthread_mutex_t _mutex; #endif void operator = (const Mutex& M); // not implemented Mutex (const Mutex& M); // not implemented - + friend class Lock; }; +#else +using Mutex = std::mutex; +#endif - -class Lock +class ILMTHREAD_EXPORT Lock { public: Lock (const Mutex& m, bool autoLock = true): - _mutex (m), - _locked (false) + _mutex (const_cast(m)), _locked (false) { if (autoLock) { @@ -122,25 +144,25 @@ class Lock _locked = true; } } - + ~Lock () { if (_locked) _mutex.unlock(); } - + void acquire () { _mutex.lock(); _locked = true; } - + void release () { _mutex.unlock(); _locked = false; } - + bool locked () { return _locked; @@ -148,11 +170,11 @@ class Lock private: - const Mutex & _mutex; - bool _locked; + Mutex & _mutex; + bool _locked; }; -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_ILM_THREAD_MUTEX_H diff --git a/3rdparty/openexr/IlmThread/IlmThreadMutexPosix.cpp b/3rdparty/openexr/IlmThread/IlmThreadMutexPosix.cpp index b2880cf903..29a265a136 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadMutexPosix.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadMutexPosix.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,19 +41,20 @@ #include "IlmBaseConfig.h" -#if HAVE_PTHREAD +#ifdef ILMBASE_FORCE_CXX03 +# if HAVE_PTHREAD -#include "IlmThreadMutex.h" -#include "Iex.h" -#include +# include "IlmThreadMutex.h" +# include "Iex.h" +# include -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER Mutex::Mutex () { if (int error = ::pthread_mutex_init (&_mutex, 0)) - Iex::throwErrnoExc ("Cannot initialize mutex (%T).", error); + IEX_INTERNAL_NAMESPACE::throwErrnoExc ("Cannot initialize mutex (%T).", error); } @@ -68,7 +69,7 @@ void Mutex::lock () const { if (int error = ::pthread_mutex_lock (&_mutex)) - Iex::throwErrnoExc ("Cannot lock mutex (%T).", error); + IEX_INTERNAL_NAMESPACE::throwErrnoExc ("Cannot lock mutex (%T).", error); } @@ -76,10 +77,11 @@ void Mutex::unlock () const { if (int error = ::pthread_mutex_unlock (&_mutex)) - Iex::throwErrnoExc ("Cannot unlock mutex (%T).", error); + IEX_INTERNAL_NAMESPACE::throwErrnoExc ("Cannot unlock mutex (%T).", error); } -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT +# endif #endif diff --git a/3rdparty/openexr/IlmThread/IlmThreadMutexWin32.cpp b/3rdparty/openexr/IlmThread/IlmThreadMutexWin32.cpp index 0e30abf490..2f7bc302e1 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadMutexWin32.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadMutexWin32.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -38,10 +38,13 @@ // //----------------------------------------------------------------------------- -#include "IlmThreadMutex.h" -#include "Iex.h" +#include "IlmBaseConfig.h" -namespace IlmThread { +#ifdef ILMBASE_FORCE_CXX03 +# include "IlmThreadMutex.h" +# include "Iex.h" + +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER Mutex::Mutex () @@ -70,4 +73,6 @@ Mutex::unlock () const } -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT + +#endif diff --git a/3rdparty/openexr/IlmThread/IlmThreadNamespace.h b/3rdparty/openexr/IlmThread/IlmThreadNamespace.h new file mode 100644 index 0000000000..a4129971a7 --- /dev/null +++ b/3rdparty/openexr/IlmThread/IlmThreadNamespace.h @@ -0,0 +1,114 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_ILMTHREADNAMESPACE_H +#define INCLUDED_ILMTHREADNAMESPACE_H + +// +// The purpose of this file is to make it possible to specify an +// ILMTHREAD_INTERNAL_NAMESPACE as a preprocessor definition and have all of +// the IlmThread symbols defined within that namespace rather than the +// standard IlmThread namespace. Those symbols are made available to client +// code through the ILMTHREAD_NAMESPACE in addition to the +// ILMTHREAD_INTERNAL_NAMESPACE. +// +// To ensure source code compatibility, the ILMTHREAD_NAMESPACE defaults to +// IlmThread and then "using namespace ILMTHREAD_INTERNAL_NAMESPACE;" brings +// all of the declarations from the ILMTHREAD_INTERNAL_NAMESPACE into the +// ILMTHREAD_NAMESPACE. This means that client code can continue to use +// syntax like IlmThread::Thread, but at link time it will resolve to a +// mangled symbol based on the ILMTHREAD_INTERNAL_NAMESPACE. +// +// As an example, if one needed to build against a newer version of IlmThread +// and have it run alongside an older version in the same application, it is +// now possible to use an internal namespace to prevent collisions between +// the older versions of IlmThread symbols and the newer ones. To do this, +// the following could be defined at build time: +// +// ILMTHREAD_INTERNAL_NAMESPACE = IlmThread_v2 +// +// This means that declarations inside IlmThread headers look like this +// (after the preprocessor has done its work): +// +// namespace IlmThread_v2 { +// ... +// class declarations +// ... +// } +// +// namespace IlmThread { +// using namespace IlmThread_v2; +// } +// + +// +// Open Source version of this file pulls in the IlmBaseConfig.h file +// for the configure time options. +// +#include "IlmBaseConfig.h" + +#ifndef ILMTHREAD_NAMESPACE +#define ILMTHREAD_NAMESPACE IlmThread +#endif + +#ifndef ILMTHREAD_INTERNAL_NAMESPACE +#define ILMTHREAD_INTERNAL_NAMESPACE ILMTHREAD_NAMESPACE +#endif + +// +// We need to be sure that we import the internal namespace into the public one. +// To do this, we use the small bit of code below which initially defines +// ILMTHREAD_INTERNAL_NAMESPACE (so it can be referenced) and then defines +// ILMTHREAD_NAMESPACE and pulls the internal symbols into the public +// namespace. +// + +namespace ILMTHREAD_INTERNAL_NAMESPACE {} +namespace ILMTHREAD_NAMESPACE { + using namespace ILMTHREAD_INTERNAL_NAMESPACE; +} + +// +// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that +// future extension to the namespace mechanism is possible without changing +// project source code. +// + +#define ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER namespace ILMTHREAD_INTERNAL_NAMESPACE { +#define ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT } + +#define ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER namespace ILMTHREAD_INTERNAL_NAMESPACE { +#define ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT } + +#endif // INCLUDED_ILMTHREADNAMESPACE_H diff --git a/3rdparty/openexr/IlmThread/IlmThreadPool.cpp b/3rdparty/openexr/IlmThread/IlmThreadPool.cpp index 3eb47d572f..174ab98c46 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadPool.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadPool.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -34,7 +34,7 @@ //----------------------------------------------------------------------------- // -// class Task, class ThreadPool, class TaskGroup +// class Task, class ThreadPool, class TaskGroup // //----------------------------------------------------------------------------- @@ -43,73 +43,185 @@ #include "IlmThreadSemaphore.h" #include "IlmThreadPool.h" #include "Iex.h" -#include +#include +#ifndef ILMBASE_FORCE_CXX03 +# include +# include +# include +#endif using namespace std; -namespace IlmThread { -namespace { - -class WorkerThread: public Thread -{ - public: - - WorkerThread (ThreadPool::Data* data); - - virtual void run (); - - private: - - ThreadPool::Data * _data; -}; - -} //namespace +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER +#if defined(__GNU_LIBRARY__) && ( __GLIBC__ < 2 || ( __GLIBC__ == 2 && __GLIBC_MINOR__ < 21 ) ) +# define ENABLE_SEM_DTOR_WORKAROUND +#endif struct TaskGroup::Data { Data (); ~Data (); - - void addTask () ; - void removeTask (); - - Semaphore isEmpty; // used to signal that the taskgroup is empty - int numPending; // number of pending tasks to still execute + + void addTask () ; + void removeTask (); +#ifndef ILMBASE_FORCE_CXX03 + std::atomic numPending; +#else + int numPending; // number of pending tasks to still execute +#endif + Semaphore isEmpty; // used to signal that the taskgroup is empty +#if defined(ENABLE_SEM_DTOR_WORKAROUND) || defined(ILMBASE_FORCE_CXX03) + // this mutex is also used to lock numPending in the legacy c++ mode... + Mutex dtorMutex; // used to work around the glibc bug: + // http://sources.redhat.com/bugzilla/show_bug.cgi?id=12674 +#endif }; struct ThreadPool::Data { + typedef ThreadPoolProvider *TPPointer; + Data (); ~Data(); - void finish (); - bool stopped () const; - void stop (); + struct SafeProvider + { + SafeProvider (Data *d, ThreadPoolProvider *p) : _data( d ), _ptr( p ) + { + } + + ~SafeProvider() + { + if ( _data ) + _data->coalesceProviderUse(); + } + SafeProvider (const SafeProvider &o) + : _data( o._data ), _ptr( o._ptr ) + { + if ( _data ) + _data->bumpProviderUse(); + } + SafeProvider &operator= (const SafeProvider &o) + { + if ( this != &o ) + { + if ( o._data ) + o._data->bumpProviderUse(); + if ( _data ) + _data->coalesceProviderUse(); + _data = o._data; + _ptr = o._ptr; + } + return *this; + } +#ifndef ILMBASE_FORCE_CXX03 + SafeProvider( SafeProvider &&o ) + : _data( o._data ), _ptr( o._ptr ) + { + o._data = nullptr; + } + SafeProvider &operator=( SafeProvider &&o ) + { + std::swap( _data, o._data ); + std::swap( _ptr, o._ptr ); + return *this; + } +#endif + inline ThreadPoolProvider *get () const + { + return _ptr; + } + ThreadPoolProvider *operator-> () const + { + return get(); + } + Data *_data; + ThreadPoolProvider *_ptr; + }; + + // NB: In C++20, there is full support for atomic shared_ptr, but that is not + // yet in use or finalized. Once stabilized, add appropriate usage here + inline SafeProvider getProvider (); + inline void coalesceProviderUse (); + inline void bumpProviderUse (); + inline void setProvider (ThreadPoolProvider *p); + +#ifdef ILMBASE_FORCE_CXX03 + Semaphore provSem; + Mutex provMutex; + int provUsers; + ThreadPoolProvider *provider; + ThreadPoolProvider *oldprovider; +#else + std::atomic provider; + std::atomic provUsers; +#endif +}; + + + +namespace { + +class DefaultWorkerThread; + +struct DefaultWorkData +{ Semaphore taskSemaphore; // threads wait on this for ready tasks - Mutex taskMutex; // mutual exclusion for the tasks list - list tasks; // the list of tasks to execute - size_t numTasks; // fast access to list size - // (list::size() can be O(n)) + mutable Mutex taskMutex; // mutual exclusion for the tasks list + vector tasks; // the list of tasks to execute Semaphore threadSemaphore; // signaled when a thread starts executing - Mutex threadMutex; // mutual exclusion for threads list - list threads; // the list of all threads - size_t numThreads; // fast access to list size - + mutable Mutex threadMutex; // mutual exclusion for threads list + vector threads; // the list of all threads + +#ifdef ILMBASE_FORCE_CXX03 bool stopping; // flag indicating whether to stop threads - Mutex stopMutex; // mutual exclusion for stopping flag -}; + mutable Mutex stopMutex; // mutual exclusion for stopping flag +#else + std::atomic hasThreads; + std::atomic stopping; +#endif + inline bool stopped () const + { +#ifdef ILMBASE_FORCE_CXX03 + Lock lock (stopMutex); + return stopping; +#else + return stopping.load( std::memory_order_relaxed ); +#endif + } + inline void stop () + { +#ifdef ILMBASE_FORCE_CXX03 + Lock lock (stopMutex); +#endif + stopping = true; + } +}; // // class WorkerThread // +class DefaultWorkerThread: public Thread +{ + public: -WorkerThread::WorkerThread (ThreadPool::Data* data): + DefaultWorkerThread (DefaultWorkData* data); + + virtual void run (); + + private: + + DefaultWorkData * _data; +}; + + +DefaultWorkerThread::DefaultWorkerThread (DefaultWorkData* data): _data (data) { start(); @@ -117,7 +229,7 @@ WorkerThread::WorkerThread (ThreadPool::Data* data): void -WorkerThread::run () +DefaultWorkerThread::run () { // // Signal that the thread has started executing @@ -127,41 +239,221 @@ WorkerThread::run () while (true) { - // + // // Wait for a task to become available - // + // _data->taskSemaphore.wait(); { Lock taskLock (_data->taskMutex); - - // + + // // If there is a task pending, pop off the next task in the FIFO - // + // - if (_data->numTasks > 0) + if (!_data->tasks.empty()) { - Task* task = _data->tasks.front(); - TaskGroup* taskGroup = task->group(); - _data->tasks.pop_front(); - _data->numTasks--; - + Task* task = _data->tasks.back(); + _data->tasks.pop_back(); taskLock.release(); + + TaskGroup* taskGroup = task->group(); task->execute(); - taskLock.acquire(); delete task; - taskGroup->_data->removeTask(); + + taskGroup->_data->removeTask (); } else if (_data->stopped()) - { + { break; + } } + } +} + + +// +// class DefaultThreadPoolProvider +// +class DefaultThreadPoolProvider : public ThreadPoolProvider +{ + public: + DefaultThreadPoolProvider(int count); + virtual ~DefaultThreadPoolProvider(); + + virtual int numThreads() const; + virtual void setNumThreads(int count); + virtual void addTask(Task *task); + + virtual void finish(); + + private: + DefaultWorkData _data; +}; + +DefaultThreadPoolProvider::DefaultThreadPoolProvider (int count) +{ + setNumThreads(count); +} + +DefaultThreadPoolProvider::~DefaultThreadPoolProvider () +{ + finish(); +} + +int +DefaultThreadPoolProvider::numThreads () const +{ + Lock lock (_data.threadMutex); + return static_cast (_data.threads.size()); +} + +void +DefaultThreadPoolProvider::setNumThreads (int count) +{ + // + // Lock access to thread list and size + // + + Lock lock (_data.threadMutex); + + size_t desired = static_cast(count); + if (desired > _data.threads.size()) + { + // + // Add more threads + // + + while (_data.threads.size() < desired) + _data.threads.push_back (new DefaultWorkerThread (&_data)); + } + else if ((size_t)count < _data.threads.size()) + { + // + // Wait until all existing threads are finished processing, + // then delete all threads. + // + finish (); + + // + // Add in new threads + // + + while (_data.threads.size() < desired) + _data.threads.push_back (new DefaultWorkerThread (&_data)); + } +#ifndef ILMBASE_FORCE_CXX03 + _data.hasThreads = !(_data.threads.empty()); +#endif +} + +void +DefaultThreadPoolProvider::addTask (Task *task) +{ + // + // Lock the threads, needed to access numThreads + // +#ifdef ILMBASE_FORCE_CXX03 + bool doPush; + { + Lock lock (_data.threadMutex); + doPush = !_data.threads.empty(); + } +#else + bool doPush = _data.hasThreads.load( std::memory_order_relaxed ); +#endif + + if ( doPush ) + { + // + // Get exclusive access to the tasks queue + // + + { + Lock taskLock (_data.taskMutex); + + // + // Push the new task into the FIFO + // + _data.tasks.push_back (task); } + + // + // Signal that we have a new task to process + // + _data.taskSemaphore.post (); + } + else + { + // this path shouldn't normally happen since we have the + // NullThreadPoolProvider, but just in case... + task->execute (); + task->group()->_data->removeTask (); + delete task; } } +void +DefaultThreadPoolProvider::finish () +{ + _data.stop(); + + // + // Signal enough times to allow all threads to stop. + // + // Wait until all threads have started their run functions. + // If we do not wait before we destroy the threads then it's + // possible that the threads have not yet called their run + // functions. + // If this happens then the run function will be called off + // of an invalid object and we will crash, most likely with + // an error like: "pure virtual method called" + // + + size_t curT = _data.threads.size(); + for (size_t i = 0; i != curT; ++i) + { + _data.taskSemaphore.post(); + _data.threadSemaphore.wait(); + } + + // + // Join all the threads + // + for (size_t i = 0; i != curT; ++i) + delete _data.threads[i]; + + Lock lock1 (_data.taskMutex); +#ifdef ILMBASE_FORCE_CXX03 + Lock lock2 (_data.stopMutex); +#endif + _data.threads.clear(); + _data.tasks.clear(); + + _data.stopping = false; +} + + +class NullThreadPoolProvider : public ThreadPoolProvider +{ + virtual ~NullThreadPoolProvider() {} + virtual int numThreads () const { return 0; } + virtual void setNumThreads (int count) + { + } + virtual void addTask (Task *t) + { + t->execute (); + t->group()->_data->removeTask (); + delete t; + } + virtual void finish () {} +}; + +} //namespace + // // struct TaskGroup::Data @@ -182,36 +474,89 @@ TaskGroup::Data::~Data () // isEmpty.wait (); + +#ifdef ENABLE_SEM_DTOR_WORKAROUND + // Update: this was fixed in v. 2.2.21, so this ifdef checks for that + // + // Alas, given the current bug in glibc we need a secondary + // syncronisation primitive here to account for the fact that + // destructing the isEmpty Semaphore in this thread can cause + // an error for a separate thread that is issuing the post() call. + // We are entitled to destruct the semaphore at this point, however, + // that post() call attempts to access data out of the associated + // memory *after* it has woken the waiting threads, including this one, + // potentially leading to invalid memory reads. + // http://sources.redhat.com/bugzilla/show_bug.cgi?id=12674 + + Lock lock (dtorMutex); +#endif } void -TaskGroup::Data::addTask () +TaskGroup::Data::addTask () { // - // Any access to the taskgroup is protected by a mutex that is - // held by the threadpool. Therefore it is safe to access - // numPending before we wait on the semaphore. + // in c++11, we use an atomic to protect numPending to avoid the + // extra lock but for c++98, to add the ability for custom thread + // pool we add the lock here // - +#if ILMBASE_FORCE_CXX03 + Lock lock (dtorMutex); +#endif if (numPending++ == 0) - isEmpty.wait (); + isEmpty.wait (); } void TaskGroup::Data::removeTask () { + // Alas, given the current bug in glibc we need a secondary + // syncronisation primitive here to account for the fact that + // destructing the isEmpty Semaphore in a separate thread can + // cause an error. Issuing the post call here the current libc + // implementation attempts to access memory *after* it has woken + // waiting threads. + // Since other threads are entitled to delete the semaphore the + // access to the memory location can be invalid. + // http://sources.redhat.com/bugzilla/show_bug.cgi?id=12674 + // Update: this bug has been fixed, but how do we know which + // glibc version we're in? + + // Further update: + // + // we could remove this if it is a new enough glibc, however + // we've changed the API to enable a custom override of a + // thread pool. In order to provide safe access to the numPending, + // we need the lock anyway, except for c++11 or newer +#ifdef ILMBASE_FORCE_CXX03 + Lock lock (dtorMutex); + if (--numPending == 0) - isEmpty.post (); + isEmpty.post (); +#else + if (--numPending == 0) + { +#ifdef ENABLE_SEM_DTOR_WORKAROUND + Lock lock (dtorMutex); +#endif + isEmpty.post (); + } +#endif } - + // // struct ThreadPool::Data // -ThreadPool::Data::Data (): numTasks (0), numThreads (0), stopping (false) +ThreadPool::Data::Data (): + provUsers (0), provider (NULL) +#ifdef ILMBASE_FORCE_CXX03 + , oldprovider (NULL) +#else +#endif { // empty } @@ -219,70 +564,130 @@ ThreadPool::Data::Data (): numTasks (0), numThreads (0), stopping (false) ThreadPool::Data::~Data() { - Lock lock (threadMutex); - finish (); +#ifdef ILMBASE_FORCE_CXX03 + provider->finish(); +#else + ThreadPoolProvider *p = provider.load( std::memory_order_relaxed ); + p->finish(); +#endif } - -void -ThreadPool::Data::finish () +inline ThreadPool::Data::SafeProvider +ThreadPool::Data::getProvider () { - stop(); +#ifdef ILMBASE_FORCE_CXX03 + Lock provLock( provMutex ); + ++provUsers; + return SafeProvider( this, provider ); +#else + provUsers.fetch_add( 1, std::memory_order_relaxed ); + return SafeProvider( this, provider.load( std::memory_order_relaxed ) ); +#endif +} - // - // Signal enough times to allow all threads to stop. - // - // Wait until all threads have started their run functions. - // If we do not wait before we destroy the threads then it's - // possible that the threads have not yet called their run - // functions. - // If this happens then the run function will be called off - // of an invalid object and we will crash, most likely with - // an error like: "pure virtual method called" - // - for (size_t i = 0; i < numThreads; i++) +inline void +ThreadPool::Data::coalesceProviderUse () +{ +#ifdef ILMBASE_FORCE_CXX03 + Lock provLock( provMutex ); + --provUsers; + if ( provUsers == 0 ) { - taskSemaphore.post(); - threadSemaphore.wait(); + if ( oldprovider ) + provSem.post(); } - - // - // Join all the threads - // - - for (list::iterator i = threads.begin(); - i != threads.end(); - ++i) +#else + int ov = provUsers.fetch_sub( 1, std::memory_order_relaxed ); + // ov is the previous value, so one means that now it might be 0 + if ( ov == 1 ) { - delete (*i); + } - - Lock lock1 (taskMutex); - Lock lock2 (stopMutex); - threads.clear(); - tasks.clear(); - numThreads = 0; - numTasks = 0; - stopping = false; +#endif } -bool -ThreadPool::Data::stopped () const +inline void +ThreadPool::Data::bumpProviderUse () { - Lock lock (stopMutex); - return stopping; +#ifdef ILMBASE_FORCE_CXX03 + Lock lock (provMutex); + ++provUsers; +#else + provUsers.fetch_add( 1, std::memory_order_relaxed ); +#endif } -void -ThreadPool::Data::stop () +inline void +ThreadPool::Data::setProvider (ThreadPoolProvider *p) { - Lock lock (stopMutex); - stopping = true; -} +#ifdef ILMBASE_FORCE_CXX03 + Lock provLock( provMutex ); + + if ( oldprovider ) + throw IEX_INTERNAL_NAMESPACE::ArgExc ("Attempt to set the thread pool provider while" + " another thread is currently setting the provider."); + + oldprovider = provider; + provider = p; + + while ( provUsers > 0 ) + { + provLock.release(); + provSem.wait(); + provLock.acquire(); + } + if ( oldprovider ) + { + oldprovider->finish(); + delete oldprovider; + oldprovider = NULL; + } +#else + ThreadPoolProvider *old = provider.load( std::memory_order_relaxed ); + do + { + if ( ! provider.compare_exchange_weak( old, p, std::memory_order_release, std::memory_order_relaxed ) ) + continue; + } while ( false ); + // wait for any other users to finish prior to deleting, given + // that these are just mostly to query the thread count or push a + // task to the queue (so fast), just spin... + // + // (well, and normally, people don't do this mid stream anyway, so + // this will be 0 99.999% of the time, but just to be safe) + // + while ( provUsers.load( std::memory_order_relaxed ) > 0 ) + std::this_thread::yield(); + + if ( old ) + { + old->finish(); + delete old; + } + + // NB: the shared_ptr mechanism is safer and means we don't have + // to have the provUsers counter since the shared_ptr keeps that + // for us. However, gcc 4.8/9 compilers which many people are + // still using even though it is 2018 forgot to add the shared_ptr + // functions... once that compiler is fully deprecated, switch to + // using the below, change provider to a std::shared_ptr and remove + // provUsers... + // +// std::shared_ptr newp( p ); +// std::shared_ptr curp = std::atomic_load_explicit( &provider, std::memory_order_relaxed ); +// do +// { +// if ( ! std::atomic_compare_exchange_weak_explicit( &provider, &curp, newp, std::memory_order_release, std::memory_order_relaxed ) ) +// continue; +// } while ( false ); +// if ( curp ) +// curp->finish(); +#endif +} // // class Task @@ -290,7 +695,8 @@ ThreadPool::Data::stop () Task::Task (TaskGroup* g): _group(g) { - // empty + if ( g ) + g->_data->addTask (); } @@ -320,14 +726,38 @@ TaskGroup::~TaskGroup () } +void +TaskGroup::finishOneTask () +{ + _data->removeTask (); +} + +// +// class ThreadPoolProvider +// + + +ThreadPoolProvider::ThreadPoolProvider() +{ +} + + +ThreadPoolProvider::~ThreadPoolProvider() +{ +} + + // // class ThreadPool // ThreadPool::ThreadPool (unsigned nthreads): - _data (new Data()) + _data (new Data) { - setNumThreads (nthreads); + if ( nthreads == 0 ) + _data->setProvider( new NullThreadPoolProvider ); + else + _data->setProvider( new DefaultThreadPoolProvider( int(nthreads) ) ); } @@ -340,8 +770,7 @@ ThreadPool::~ThreadPool () int ThreadPool::numThreads () const { - Lock lock (_data->threadMutex); - return _data->numThreads; + return _data->getProvider ()->numThreads (); } @@ -349,87 +778,53 @@ void ThreadPool::setNumThreads (int count) { if (count < 0) - throw Iex::ArgExc ("Attempt to set the number of threads " + throw IEX_INTERNAL_NAMESPACE::ArgExc ("Attempt to set the number of threads " "in a thread pool to a negative value."); - // - // Lock access to thread list and size - // - - Lock lock (_data->threadMutex); - - if ((size_t)count > _data->numThreads) + bool doReset = false; { - // - // Add more threads - // + Data::SafeProvider sp = _data->getProvider (); + int curT = sp->numThreads (); + if ( curT == count ) + return; - while (_data->numThreads < (size_t)count) + if ( curT == 0 ) { - _data->threads.push_back (new WorkerThread (_data)); - _data->numThreads++; + NullThreadPoolProvider *npp = dynamic_cast( sp.get() ); + if ( npp ) + doReset = true; } - } - else if ((size_t)count < _data->numThreads) - { - // - // Wait until all existing threads are finished processing, - // then delete all threads. - // - - _data->finish (); - - // - // Add in new threads - // - - while (_data->numThreads < (size_t)count) + else if ( count == 0 ) { - _data->threads.push_back (new WorkerThread (_data)); - _data->numThreads++; + DefaultThreadPoolProvider *dpp = dynamic_cast( sp.get() ); + if ( dpp ) + doReset = true; } + if ( ! doReset ) + sp->setNumThreads( count ); } -} - -void -ThreadPool::addTask (Task* task) -{ - // - // Lock the threads, needed to access numThreads - // - - Lock lock (_data->threadMutex); - - if (_data->numThreads == 0) + if ( doReset ) { - task->execute (); - delete task; + if ( count == 0 ) + _data->setProvider( new NullThreadPoolProvider ); + else + _data->setProvider( new DefaultThreadPoolProvider( count ) ); } - else - { - // - // Get exclusive access to the tasks queue - // +} - { - Lock taskLock (_data->taskMutex); - // - // Push the new task into the FIFO - // - - _data->tasks.push_back (task); - _data->numTasks++; - task->group()->_data->addTask(); - } +void +ThreadPool::setThreadProvider (ThreadPoolProvider *provider) +{ + _data->setProvider (provider); +} - // - // Signal that we have a new task to process - // - _data->taskSemaphore.post (); - } +void +ThreadPool::addTask (Task* task) +{ + _data->getProvider ()->addTask (task); } @@ -439,7 +834,7 @@ ThreadPool::globalThreadPool () // // The global thread pool // - + static ThreadPool gThreadPool (0); return gThreadPool; @@ -453,4 +848,4 @@ ThreadPool::addGlobalTask (Task* task) } -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmThread/IlmThreadPool.h b/3rdparty/openexr/IlmThread/IlmThreadPool.h index e806db9f8c..85b3de2f29 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadPool.h +++ b/3rdparty/openexr/IlmThread/IlmThreadPool.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -35,19 +35,20 @@ #ifndef INCLUDED_ILM_THREAD_POOL_H #define INCLUDED_ILM_THREAD_POOL_H + //----------------------------------------------------------------------------- // // class Task, class ThreadPool, class TaskGroup // // Class ThreadPool manages a set of worker threads and accepts // tasks for processing. Tasks added to the thread pool are -// executed concurrently by the worker threads. -// -// Class Thread provides an abstract interface for a task which +// executed concurrently by the worker threads. +// +// Class Task provides an abstract interface for a task which // a ThreadPool works on. Derived classes need to implement the // execute() function which performs the actual task. // -// Class TaskTroup allows synchronization on the completion of a set +// Class TaskGroup allows synchronization on the completion of a set // of tasks. Every task that is added to a ThreadPool belongs to a // single TaskGroup. The destructor of the TaskGroup waits for all // tasks in the group to finish. @@ -60,19 +61,59 @@ // //----------------------------------------------------------------------------- -namespace IlmThread { +#include "IlmThreadNamespace.h" +#include "IlmThreadExport.h" + +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER class TaskGroup; class Task; +//------------------------------------------------------- +// ThreadPoolProvider -- this is a pure virtual interface +// enabling custom overloading of the threads used and how +// the implementation of the processing of tasks +// is implemented +//------------------------------------------------------- +class ILMTHREAD_EXPORT ThreadPoolProvider +{ + public: + ThreadPoolProvider(); + virtual ~ThreadPoolProvider(); + + // as in ThreadPool below + virtual int numThreads () const = 0; + // as in ThreadPool below + virtual void setNumThreads (int count) = 0; + // as in ThreadPool below + virtual void addTask (Task* task) = 0; + + // Ensure that all tasks in this set are finished + // and threads shutdown + virtual void finish () = 0; + + // Make the provider non-copyable +#if __cplusplus >= 201103L + ThreadPoolProvider (const ThreadPoolProvider &) = delete; + ThreadPoolProvider &operator= (const ThreadPoolProvider &) = delete; + ThreadPoolProvider (ThreadPoolProvider &&) = delete; + ThreadPoolProvider &operator= (ThreadPoolProvider &&) = delete; +#else + private: + ThreadPoolProvider (const ThreadPoolProvider &); + ThreadPoolProvider &operator= (const ThreadPoolProvider &); +#endif +}; -class ThreadPool +class ILMTHREAD_EXPORT ThreadPool { public: + //------------------------------------------------------- // Constructor -- creates numThreads worker threads which - // wait until a task is available. + // wait until a task is available, + // using a default ThreadPoolProvider //------------------------------------------------------- ThreadPool (unsigned numThreads = 0); @@ -84,7 +125,7 @@ class ThreadPool //----------------------------------------------------------- virtual ~ThreadPool (); - + //-------------------------------------------------------- // Query and set the number of worker threads in the pool. @@ -93,10 +134,22 @@ class ThreadPool // thread as this will almost certainly cause a deadlock // or crash. //-------------------------------------------------------- - + int numThreads () const; void setNumThreads (int count); + //-------------------------------------------------------- + // Set the thread provider for the pool. + // + // The ThreadPool takes ownership of the ThreadPoolProvider + // and will call delete on it when it is finished or when + // it is changed + // + // Warning: never call setThreadProvider from within a worker + // thread as this will almost certainly cause a deadlock + // or crash. + //-------------------------------------------------------- + void setThreadProvider (ThreadPoolProvider *provider); //------------------------------------------------------------ // Add a task for processing. The ThreadPool can handle any @@ -106,12 +159,12 @@ class ThreadPool //------------------------------------------------------------ void addTask (Task* task); - + //------------------------------------------- // Access functions for the global threadpool //------------------------------------------- - + static ThreadPool& globalThreadPool (); static void addGlobalTask (Task* task); @@ -123,7 +176,7 @@ class ThreadPool }; -class Task +class ILMTHREAD_EXPORT Task { public: @@ -139,18 +192,23 @@ class Task }; -class TaskGroup +class ILMTHREAD_EXPORT TaskGroup { public: - TaskGroup(); + TaskGroup(); ~TaskGroup(); + // marks one task as finished + // should be used by the thread pool provider to notify + // as it finishes tasks + void finishOneTask (); + struct Data; Data* const _data; }; -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_ILM_THREAD_POOL_H diff --git a/3rdparty/openexr/IlmThread/IlmThreadPosix.cpp b/3rdparty/openexr/IlmThread/IlmThreadPosix.cpp index 6b6f1ae0d5..4aee3f3ca2 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadPosix.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadPosix.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,6 +42,7 @@ #include "IlmBaseConfig.h" #if HAVE_PTHREAD +#ifdef ILMBASE_FORCE_CXX03 #include "IlmThread.h" #include "Iex.h" @@ -52,7 +53,7 @@ extern "C" typedef void * (* Start) (void *); } -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER bool @@ -89,10 +90,11 @@ void Thread::start () { if (int error = ::pthread_create (&_thread, 0, Start (threadLoop), this)) - Iex::throwErrnoExc ("Cannot create new thread (%T).", error); + IEX_NAMESPACE::throwErrnoExc ("Cannot create new thread (%T).", error); } -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT #endif +#endif diff --git a/3rdparty/openexr/IlmThread/IlmThreadSemaphore.cpp b/3rdparty/openexr/IlmThread/IlmThreadSemaphore.cpp index de8998a1a9..26ae76368a 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadSemaphore.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadSemaphore.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,7 +44,7 @@ #if !defined (_WIN32) && !(_WIN64) && !(HAVE_PTHREAD) #include "IlmThreadSemaphore.h" -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER Semaphore::Semaphore (unsigned int value) {} @@ -55,6 +55,6 @@ void Semaphore::post () {} int Semaphore::value () const {return 0;} -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT #endif diff --git a/3rdparty/openexr/IlmThread/IlmThreadSemaphore.h b/3rdparty/openexr/IlmThread/IlmThreadSemaphore.h index 8e13cf9622..adc52cd44e 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadSemaphore.h +++ b/3rdparty/openexr/IlmThread/IlmThreadSemaphore.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,23 +43,32 @@ //----------------------------------------------------------------------------- #include "IlmBaseConfig.h" +#include "IlmThreadExport.h" +#include "IlmThreadNamespace.h" #if defined _WIN32 || defined _WIN64 - #ifdef NOMINMAX - #undef NOMINMAX - #endif - #define NOMINMAX - #include -#elif HAVE_PTHREAD && !HAVE_POSIX_SEMAPHORES - #include -#elif HAVE_PTHREAD && HAVE_POSIX_SEMAPHORES - #include +# ifdef NOMINMAX +# undef NOMINMAX +# endif +# define NOMINMAX +# include +#elif HAVE_POSIX_SEMAPHORES +# include +#else +# ifdef ILMBASE_FORCE_CXX03 +# if HAVE_PTHREAD +# include +# endif +# else +# include +# include +# endif #endif -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER -class Semaphore +class ILMTHREAD_EXPORT Semaphore { public: @@ -73,38 +82,46 @@ class Semaphore private: - #if defined _WIN32 || defined _WIN64 - - mutable HANDLE _semaphore; - - #elif HAVE_PTHREAD && !HAVE_POSIX_SEMAPHORES - - // - // If the platform has Posix threads but no semapohores, - // then we implement them ourselves using condition variables - // - - struct sema_t - { - unsigned int count; - unsigned long numWaiting; - pthread_mutex_t mutex; - pthread_cond_t nonZero; - }; - - mutable sema_t _semaphore; - - #elif HAVE_PTHREAD && HAVE_POSIX_SEMAPHORES - - mutable sem_t _semaphore; +#if defined _WIN32 || defined _WIN64 - #endif + mutable HANDLE _semaphore; + +#elif HAVE_POSIX_SEMAPHORES + + mutable sem_t _semaphore; + +#else + // + // If the platform has Posix threads but no semapohores, + // then we implement them ourselves using condition variables + // + + struct sema_t + { + unsigned int count; + unsigned long numWaiting; +# if ILMBASE_FORCE_CXX03 +# if HAVE_PTHREAD + pthread_mutex_t mutex; + pthread_cond_t nonZero; +# else +# error unhandled legacy setup +# endif +# else + std::mutex mutex; + std::condition_variable nonZero; +# endif + }; + + mutable sema_t _semaphore; + +#endif void operator = (const Semaphore& s); // not implemented Semaphore (const Semaphore& s); // not implemented }; -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_ILM_THREAD_SEMAPHORE_H diff --git a/3rdparty/openexr/IlmThread/IlmThreadSemaphorePosix.cpp b/3rdparty/openexr/IlmThread/IlmThreadSemaphorePosix.cpp index 745819ff25..400d90effc 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadSemaphorePosix.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadSemaphorePosix.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,14 +46,15 @@ #include "IlmThreadSemaphore.h" #include "Iex.h" #include +#include -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER Semaphore::Semaphore (unsigned int value) { if (::sem_init (&_semaphore, 0, value)) - Iex::throwErrnoExc ("Cannot initialize semaphore (%T)."); + IEX_NAMESPACE::throwErrnoExc ("Cannot initialize semaphore (%T)."); } @@ -67,7 +68,9 @@ Semaphore::~Semaphore () void Semaphore::wait () { - ::sem_wait (&_semaphore); + while( ::sem_wait( &_semaphore ) == -1 && errno == EINTR ) + { + } } @@ -82,7 +85,7 @@ void Semaphore::post () { if (::sem_post (&_semaphore)) - Iex::throwErrnoExc ("Post operation on semaphore failed (%T)."); + IEX_NAMESPACE::throwErrnoExc ("Post operation on semaphore failed (%T)."); } @@ -92,12 +95,12 @@ Semaphore::value () const int value; if (::sem_getvalue (&_semaphore, &value)) - Iex::throwErrnoExc ("Cannot read semaphore value (%T)."); + IEX_NAMESPACE::throwErrnoExc ("Cannot read semaphore value (%T)."); return value; } -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT #endif diff --git a/3rdparty/openexr/IlmThread/IlmThreadSemaphorePosixCompat.cpp b/3rdparty/openexr/IlmThread/IlmThreadSemaphorePosixCompat.cpp index 56769e7c27..fa41bb6d4f 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadSemaphorePosixCompat.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadSemaphorePosixCompat.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,22 +42,22 @@ #include "IlmBaseConfig.h" -#if HAVE_PTHREAD && !HAVE_POSIX_SEMAPHORES +#if (!HAVE_POSIX_SEMAPHORES) && !defined (_WIN32) && ! defined (_WIN64) #include "IlmThreadSemaphore.h" #include "Iex.h" #include -namespace IlmThread { - +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER +#if ILMBASE_FORCE_CXX03 && HAVE_PTHREAD Semaphore::Semaphore (unsigned int value) { if (int error = ::pthread_mutex_init (&_semaphore.mutex, 0)) - Iex::throwErrnoExc ("Cannot initialize mutex (%T).", error); + IEX_NAMESPACE::throwErrnoExc ("Cannot initialize mutex (%T).", error); if (int error = ::pthread_cond_init (&_semaphore.nonZero, 0)) - Iex::throwErrnoExc ("Cannot initialize condition variable (%T).", + IEX_NAMESPACE::throwErrnoExc ("Cannot initialize condition variable (%T).", error); _semaphore.count = value; @@ -85,12 +85,12 @@ Semaphore::wait () { if (int error = ::pthread_cond_wait (&_semaphore.nonZero, &_semaphore.mutex)) - { + { ::pthread_mutex_unlock (&_semaphore.mutex); - Iex::throwErrnoExc ("Cannot wait on condition variable (%T).", - error); - } + IEX_NAMESPACE::throwErrnoExc ("Cannot wait on condition variable (%T).", + error); + } } _semaphore.numWaiting--; @@ -104,7 +104,7 @@ bool Semaphore::tryWait () { ::pthread_mutex_lock (&_semaphore.mutex); - + if (_semaphore.count == 0) { ::pthread_mutex_unlock (&_semaphore.mutex); @@ -126,13 +126,22 @@ Semaphore::post () if (_semaphore.numWaiting > 0) { - if (int error = ::pthread_cond_signal (&_semaphore.nonZero)) - { + int error; + if (_semaphore.numWaiting > 1 && _semaphore.count > 1) + { + error = ::pthread_cond_broadcast (&_semaphore.nonZero); + } + else + { + error = ::pthread_cond_signal (&_semaphore.nonZero); + } + if (error) + { ::pthread_mutex_unlock (&_semaphore.mutex); - Iex::throwErrnoExc ("Cannot signal condition variable (%T).", + IEX_NAMESPACE::throwErrnoExc ("Cannot signal condition variable (%T).", error); - } + } } _semaphore.count++; @@ -148,8 +157,71 @@ Semaphore::value () const ::pthread_mutex_unlock (&_semaphore.mutex); return value; } +#else +Semaphore::Semaphore (unsigned int value) +{ + _semaphore.count = value; + _semaphore.numWaiting = 0; +} + + +Semaphore::~Semaphore () +{ +} + + +void +Semaphore::wait () +{ + std::unique_lock lk(_semaphore.mutex); + + _semaphore.numWaiting++; + + while (_semaphore.count == 0) + _semaphore.nonZero.wait (lk); + + _semaphore.numWaiting--; + _semaphore.count--; +} + + +bool +Semaphore::tryWait () +{ + std::lock_guard lk(_semaphore.mutex); + + if (_semaphore.count == 0) + return false; + + _semaphore.count--; + return true; +} + + +void +Semaphore::post () +{ + std::lock_guard lk(_semaphore.mutex); + + _semaphore.count++; + if (_semaphore.numWaiting > 0) + { + if (_semaphore.count > 1) + _semaphore.nonZero.notify_all(); + else + _semaphore.nonZero.notify_one(); + } +} + +int +Semaphore::value () const +{ + std::lock_guard lk(_semaphore.mutex); + return _semaphore.count; +} +#endif -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT #endif diff --git a/3rdparty/openexr/IlmThread/IlmThreadSemaphoreWin32.cpp b/3rdparty/openexr/IlmThread/IlmThreadSemaphoreWin32.cpp index 0c6e2ae8ce..3e5c372306 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadSemaphoreWin32.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadSemaphoreWin32.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,9 +44,9 @@ #include #include -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER -using namespace Iex; +using namespace IEX_NAMESPACE; namespace { @@ -58,22 +58,22 @@ errorString () std::string message; // - // Call FormatMessage() to allow for message + // Call FormatMessage() to allow for message // text to be acquired from the system. // if (bufferLength = FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM, - 0, - GetLastError (), - MAKELANGID (LANG_NEUTRAL, - SUBLANG_DEFAULT), - (LPSTR) &messageBuffer, - 0, - NULL)) + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM, + 0, + GetLastError (), + MAKELANGID (LANG_NEUTRAL, + SUBLANG_DEFAULT), + (LPSTR) &messageBuffer, + 0, + NULL)) { - message = messageBuffer; + message = messageBuffer; LocalFree (messageBuffer); } @@ -87,8 +87,8 @@ Semaphore::Semaphore (unsigned int value) { if ((_semaphore = ::CreateSemaphore (0, value, 0x7fffffff, 0)) == 0) { - THROW (LogicExc, "Could not create semaphore " - "(" << errorString() << ")."); + THROW (LogicExc, "Could not create semaphore " + "(" << errorString() << ")."); } } @@ -105,8 +105,8 @@ Semaphore::wait() { if (::WaitForSingleObject (_semaphore, INFINITE) != WAIT_OBJECT_0) { - THROW (LogicExc, "Could not wait on semaphore " - "(" << errorString() << ")."); + THROW (LogicExc, "Could not wait on semaphore " + "(" << errorString() << ")."); } } @@ -123,8 +123,8 @@ Semaphore::post() { if (!::ReleaseSemaphore (_semaphore, 1, 0)) { - THROW (LogicExc, "Could not post on semaphore " - "(" << errorString() << ")."); + THROW (LogicExc, "Could not post on semaphore " + "(" << errorString() << ")."); } } @@ -136,11 +136,12 @@ Semaphore::value() const if (!::ReleaseSemaphore (_semaphore, 0, &v) || v < 0) { - THROW (LogicExc, "Could not get value of semaphore " - "(" << errorString () << ")."); + THROW (LogicExc, "Could not get value of semaphore " + "(" << errorString () << ")."); } return v; } -} // namespace IlmThread + +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/IlmThread/IlmThreadWin32.cpp b/3rdparty/openexr/IlmThread/IlmThreadWin32.cpp index 46a425035c..43ec23f6e6 100644 --- a/3rdparty/openexr/IlmThread/IlmThreadWin32.cpp +++ b/3rdparty/openexr/IlmThread/IlmThreadWin32.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2005-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,12 +39,16 @@ //----------------------------------------------------------------------------- +#include "IlmBaseConfig.h" + +#ifdef ILMBASE_FORCE_CXX03 + #include "IlmThread.h" #include "Iex.h" #include #include -namespace IlmThread { +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_ENTER bool @@ -88,8 +92,10 @@ Thread::start () _thread = (HANDLE)::_beginthreadex (0, 0, &threadLoop, this, 0, &id); if (_thread == 0) - Iex::throwErrnoExc ("Cannot create new thread (%T)."); + IEX_NAMESPACE::throwErrnoExc ("Cannot create new thread (%T)."); } -} // namespace IlmThread +ILMTHREAD_INTERNAL_NAMESPACE_SOURCE_EXIT + +#endif diff --git a/3rdparty/openexr/Imath/ImathBox.cpp b/3rdparty/openexr/Imath/ImathBox.cpp new file mode 100644 index 0000000000..07bddfd3bd --- /dev/null +++ b/3rdparty/openexr/Imath/ImathBox.cpp @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#include "ImathBox.h" + +// this file is necessary for template instantiation on windows diff --git a/3rdparty/openexr/Imath/ImathBox.h b/3rdparty/openexr/Imath/ImathBox.h index 8a013851f1..45165ff761 100644 --- a/3rdparty/openexr/Imath/ImathBox.h +++ b/3rdparty/openexr/Imath/ImathBox.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,13 +41,13 @@ // class Imath::Box // -------------------------------- // -// This class imposes the following requirements on its +// This class imposes the following requirements on its // parameter class: -// +// // 1) The class T must implement these operators: -// + - < > <= >= = -// with the signature (T,T) and the expected -// return values for a numeric type. +// + - < > <= >= = +// with the signature (T,T) and the expected +// return values for a numeric type. // // 2) The class T must implement operator= // with the signature (T,float and/or double) @@ -63,11 +63,12 @@ //------------------------------------------------------------------- #include "ImathVec.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER -template +template class Box { public: @@ -83,14 +84,14 @@ class Box // Constructors - an "empty" box is created by default //----------------------------------------------------- - Box (); + Box (); Box (const T &point); Box (const T &minT, const T &maxT); //-------------------- // Operators: ==, != //-------------------- - + bool operator == (const Box &src) const; bool operator != (const Box &src) const; @@ -101,7 +102,7 @@ class Box void makeEmpty (); void extendBy (const T &point); void extendBy (const Box &box); - void makeInfinite (); + void makeInfinite (); //--------------------------------------------------- // Query functions - these compute results each time @@ -202,11 +203,11 @@ Box::extendBy(const T &point) { for (unsigned int i = 0; i < min.dimensions(); i++) { - if (point[i] < min[i]) - min[i] = point[i]; + if (point[i] < min[i]) + min[i] = point[i]; - if (point[i] > max[i]) - max[i] = point[i]; + if (point[i] > max[i]) + max[i] = point[i]; } } @@ -217,11 +218,11 @@ Box::extendBy(const Box &box) { for (unsigned int i = 0; i < min.dimensions(); i++) { - if (box.min[i] < min[i]) - min[i] = box.min[i]; + if (box.min[i] < min[i]) + min[i] = box.min[i]; - if (box.max[i] > max[i]) - max[i] = box.max[i]; + if (box.max[i] > max[i]) + max[i] = box.max[i]; } } @@ -233,7 +234,7 @@ Box::intersects(const T &point) const for (unsigned int i = 0; i < min.dimensions(); i++) { if (point[i] < min[i] || point[i] > max[i]) - return false; + return false; } return true; @@ -247,28 +248,28 @@ Box::intersects(const Box &box) const for (unsigned int i = 0; i < min.dimensions(); i++) { if (box.max[i] < min[i] || box.min[i] > max[i]) - return false; + return false; } return true; } -template +template inline T -Box::size() const -{ +Box::size() const +{ if (isEmpty()) - return T (0); + return T (0); return max - min; } -template +template inline T -Box::center() const -{ +Box::center() const +{ return (max + min) / 2; } @@ -280,7 +281,7 @@ Box::isEmpty() const for (unsigned int i = 0; i < min.dimensions(); i++) { if (max[i] < min[i]) - return true; + return true; } return false; @@ -293,7 +294,7 @@ Box::isInfinite() const for (unsigned int i = 0; i < min.dimensions(); i++) { if (min[i] != T::baseTypeMin() || max[i] != T::baseTypeMax()) - return false; + return false; } return true; @@ -307,7 +308,7 @@ Box::hasVolume() const for (unsigned int i = 0; i < min.dimensions(); i++) { if (max[i] <= min[i]) - return false; + return false; } return true; @@ -323,8 +324,8 @@ Box::majorAxis() const for (unsigned int i = 1; i < min.dimensions(); i++) { - if (s[i] > s[major]) - major = i; + if (s[i] > s[major]) + major = i; } return major; @@ -354,7 +355,7 @@ class Box > // Constructors - an "empty" box is created by default //----------------------------------------------------- - Box(); + Box(); Box (const Vec2 &point); Box (const Vec2 &minT, const Vec2 &maxT); @@ -512,10 +513,10 @@ Box >::intersects (const Box > &box) const } -template +template inline Vec2 -Box >::size() const -{ +Box >::size() const +{ if (isEmpty()) return Vec2 (0); @@ -523,10 +524,10 @@ Box >::size() const } -template +template inline Vec2 -Box >::center() const -{ +Box >::center() const +{ return (max + min) / 2; } @@ -549,7 +550,7 @@ Box > ::isInfinite() const if (min[0] != limits::min() || max[0] != limits::max() || min[1] != limits::min() || max[1] != limits::max()) return false; - + return true; } @@ -596,7 +597,7 @@ class Box > // Constructors - an "empty" box is created by default //----------------------------------------------------- - Box(); + Box(); Box (const Vec3 &point); Box (const Vec3 &minT, const Vec3 &maxT); @@ -769,10 +770,10 @@ Box >::intersects (const Box > &box) const } -template +template inline Vec3 -Box >::size() const -{ +Box >::size() const +{ if (isEmpty()) return Vec3 (0); @@ -780,10 +781,10 @@ Box >::size() const } -template +template inline Vec3 -Box >::center() const -{ +Box >::center() const +{ return (max + min) / 2; } @@ -808,7 +809,7 @@ Box >::isInfinite() const min[1] != limits::min() || max[1] != limits::max() || min[2] != limits::min() || max[2] != limits::max()) return false; - + return true; } @@ -843,8 +844,6 @@ Box >::majorAxis() const } +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT - -} // namespace Imath - -#endif +#endif // INCLUDED_IMATHBOX_H diff --git a/3rdparty/openexr/Imath/ImathBoxAlgo.h b/3rdparty/openexr/Imath/ImathBoxAlgo.h index 5379e8f465..63bd2f635b 100644 --- a/3rdparty/openexr/Imath/ImathBoxAlgo.h +++ b/3rdparty/openexr/Imath/ImathBoxAlgo.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002-2010, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -67,8 +67,8 @@ // Vec3 &enterPoint, // Vec3 &exitPoint) // -// bool intersects(const Box> &box, -// const Line3 &ray, +// bool intersects(const Box> &box, +// const Line3 &ray, // Vec3 intersectionPoint) // // bool intersects(const Box> &box, const Line3 &ray) @@ -79,8 +79,9 @@ #include "ImathMatrix.h" #include "ImathLineAlgo.h" #include "ImathPlane.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template @@ -96,12 +97,12 @@ clip (const T &p, const Box &box) for (int i = 0; i < int (box.min.dimensions()); i++) { - if (p[i] < box.min[i]) - q[i] = box.min[i]; - else if (p[i] > box.max[i]) - q[i] = box.max[i]; - else - q[i] = p[i]; + if (p[i] < box.min[i]) + q[i] = box.min[i]; + else if (p[i] > box.max[i]) + q[i] = box.max[i]; + else + q[i] = p[i]; } return q; @@ -128,31 +129,31 @@ closestPointOnBox (const Vec3 &p, const Box< Vec3 > &box) // if (box.isEmpty()) - return p; + return p; Vec3 q = closestPointInBox (p, box); if (q == p) { - Vec3 d1 = p - box.min; - Vec3 d2 = box.max - p; + Vec3 d1 = p - box.min; + Vec3 d2 = box.max - p; - Vec3 d ((d1.x < d2.x)? d1.x: d2.x, - (d1.y < d2.y)? d1.y: d2.y, - (d1.z < d2.z)? d1.z: d2.z); + Vec3 d ((d1.x < d2.x)? d1.x: d2.x, + (d1.y < d2.y)? d1.y: d2.y, + (d1.z < d2.z)? d1.z: d2.z); - if (d.x < d.y && d.x < d.z) - { - q.x = (d1.x < d2.x)? box.min.x: box.max.x; - } - else if (d.y < d.z) - { - q.y = (d1.y < d2.y)? box.min.y: box.max.y; - } - else - { - q.z = (d1.z < d2.z)? box.min.z: box.max.z; - } + if (d.x < d.y && d.x < d.z) + { + q.x = (d1.x < d2.x)? box.min.x: box.max.x; + } + else if (d.y < d.z) + { + q.y = (d1.y < d2.y)? box.min.y: box.max.y; + } + else + { + q.z = (d1.z < d2.z)? box.min.z: box.max.z; + } } return q; @@ -178,7 +179,7 @@ transform (const Box< Vec3 > &box, const Matrix44 &m) // if (box.isEmpty() || box.isInfinite()) - return box; + return box; // // If the last column of m is (0 0 0 1) then m is an affine @@ -187,33 +188,33 @@ transform (const Box< Vec3 > &box, const Matrix44 &m) if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1) { - Box< Vec3 > newBox; + Box< Vec3 > newBox; - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { - newBox.min[i] = newBox.max[i] = (S) m[3][i]; + newBox.min[i] = newBox.max[i] = (S) m[3][i]; - for (int j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) { - S a, b; + S a, b; - a = (S) m[j][i] * box.min[j]; - b = (S) m[j][i] * box.max[j]; + a = (S) m[j][i] * box.min[j]; + b = (S) m[j][i] * box.max[j]; - if (a < b) + if (a < b) { - newBox.min[i] += a; - newBox.max[i] += b; - } - else + newBox.min[i] += a; + newBox.max[i] += b; + } + else { - newBox.min[i] += b; - newBox.max[i] += a; - } - } - } + newBox.min[i] += b; + newBox.max[i] += a; + } + } + } - return newBox; + return newBox; } // @@ -235,8 +236,8 @@ transform (const Box< Vec3 > &box, const Matrix44 &m) Box< Vec3 > newBox; - for (int i = 0; i < 8; i++) - newBox.extendBy (points[i] * m); + for (int i = 0; i < 8; i++) + newBox.extendBy (points[i] * m); return newBox; } @@ -263,7 +264,7 @@ transform (const Box< Vec3 > &box, if (box.isEmpty() || box.isInfinite()) { - return; + return; } // @@ -273,31 +274,31 @@ transform (const Box< Vec3 > &box, if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1) { - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { - result.min[i] = result.max[i] = (S) m[3][i]; + result.min[i] = result.max[i] = (S) m[3][i]; - for (int j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) { - S a, b; + S a, b; - a = (S) m[j][i] * box.min[j]; - b = (S) m[j][i] * box.max[j]; + a = (S) m[j][i] * box.min[j]; + b = (S) m[j][i] * box.max[j]; - if (a < b) + if (a < b) { - result.min[i] += a; - result.max[i] += b; - } - else + result.min[i] += a; + result.max[i] += b; + } + else { - result.min[i] += b; - result.max[i] += a; - } - } - } + result.min[i] += b; + result.max[i] += a; + } + } + } - return; + return; } // @@ -317,8 +318,8 @@ transform (const Box< Vec3 > &box, points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2]; points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2]; - for (int i = 0; i < 8; i++) - result.extendBy (points[i] * m); + for (int i = 0; i < 8; i++) + result.extendBy (points[i] * m); } @@ -337,37 +338,37 @@ affineTransform (const Box< Vec3 > &box, const Matrix44 &m) if (box.isEmpty() || box.isInfinite()) { - // - // A transformed empty or infinite box is still empty or infinite - // + // + // A transformed empty or infinite box is still empty or infinite + // - return box; + return box; } Box< Vec3 > newBox; - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { - newBox.min[i] = newBox.max[i] = (S) m[3][i]; + newBox.min[i] = newBox.max[i] = (S) m[3][i]; - for (int j = 0; j < 3; j++) - { - S a, b; + for (int j = 0; j < 3; j++) + { + S a, b; - a = (S) m[j][i] * box.min[j]; - b = (S) m[j][i] * box.max[j]; + a = (S) m[j][i] * box.min[j]; + b = (S) m[j][i] * box.max[j]; - if (a < b) - { - newBox.min[i] += a; - newBox.max[i] += b; - } - else - { - newBox.min[i] += b; - newBox.max[i] += a; - } - } + if (a < b) + { + newBox.min[i] += a; + newBox.max[i] += b; + } + else + { + newBox.min[i] += b; + newBox.max[i] += a; + } + } } return newBox; @@ -390,44 +391,44 @@ affineTransform (const Box< Vec3 > &box, if (box.isEmpty()) { - // - // A transformed empty box is still empty - // + // + // A transformed empty box is still empty + // result.makeEmpty(); - return; + return; } if (box.isInfinite()) { - // - // A transformed infinite box is still infinite - // + // + // A transformed infinite box is still infinite + // result.makeInfinite(); - return; + return; } - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { - result.min[i] = result.max[i] = (S) m[3][i]; + result.min[i] = result.max[i] = (S) m[3][i]; - for (int j = 0; j < 3; j++) - { - S a, b; + for (int j = 0; j < 3; j++) + { + S a, b; - a = (S) m[j][i] * box.min[j]; - b = (S) m[j][i] * box.max[j]; + a = (S) m[j][i] * box.min[j]; + b = (S) m[j][i] * box.max[j]; - if (a < b) - { - result.min[i] += a; - result.max[i] += b; - } - else - { - result.min[i] += b; - result.max[i] += a; - } - } + if (a < b) + { + result.min[i] += a; + result.max[i] += b; + } + else + { + result.min[i] += b; + result.max[i] += a; + } + } } } @@ -435,9 +436,9 @@ affineTransform (const Box< Vec3 > &box, template bool findEntryAndExitPoints (const Line3 &r, - const Box > &b, - Vec3 &entry, - Vec3 &exit) + const Box > &b, + Vec3 &entry, + Vec3 &exit) { // // Compute the points where a ray, r, enters and exits a box, b: @@ -463,11 +464,11 @@ findEntryAndExitPoints (const Line3 &r, if (b.isEmpty()) { - // - // No ray intersects an empty box - // + // + // No ray intersects an empty box + // - return false; + return false; } // @@ -499,73 +500,73 @@ findEntryAndExitPoints (const Line3 &r, if (r.dir.x >= 0) { - T d1 = b.max.x - r.pos.x; - T d2 = b.min.x - r.pos.x; - - if (r.dir.x > 1 || - (abs (d1) < TMAX * r.dir.x && - abs (d2) < TMAX * r.dir.x)) - { - T t1 = d1 / r.dir.x; - T t2 = d2 / r.dir.x; - - if (tBackMin > t1) - { - tBackMin = t1; - - exit.x = b.max.x; - exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); - exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); - } - - if (tFrontMax < t2) - { - tFrontMax = t2; - - entry.x = b.min.x; - entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); - entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); - } - } - else if (r.pos.x < b.min.x || r.pos.x > b.max.x) - { - return false; - } + T d1 = b.max.x - r.pos.x; + T d2 = b.min.x - r.pos.x; + + if (r.dir.x > 1 || + (abs (d1) < TMAX * r.dir.x && + abs (d2) < TMAX * r.dir.x)) + { + T t1 = d1 / r.dir.x; + T t2 = d2 / r.dir.x; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = b.max.x; + exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); + exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = b.min.x; + entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); + entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); + } + } + else if (r.pos.x < b.min.x || r.pos.x > b.max.x) + { + return false; + } } else // r.dir.x < 0 { - T d1 = b.min.x - r.pos.x; - T d2 = b.max.x - r.pos.x; + T d1 = b.min.x - r.pos.x; + T d2 = b.max.x - r.pos.x; - if (r.dir.x < -1 || - (abs (d1) < -TMAX * r.dir.x && - abs (d2) < -TMAX * r.dir.x)) - { - T t1 = d1 / r.dir.x; - T t2 = d2 / r.dir.x; + if (r.dir.x < -1 || + (abs (d1) < -TMAX * r.dir.x && + abs (d2) < -TMAX * r.dir.x)) + { + T t1 = d1 / r.dir.x; + T t2 = d2 / r.dir.x; - if (tBackMin > t1) - { - tBackMin = t1; + if (tBackMin > t1) + { + tBackMin = t1; - exit.x = b.min.x; - exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); - exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); - } + exit.x = b.min.x; + exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); + exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); + } - if (tFrontMax < t2) - { - tFrontMax = t2; + if (tFrontMax < t2) + { + tFrontMax = t2; - entry.x = b.max.x; - entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); - entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); - } - } - else if (r.pos.x < b.min.x || r.pos.x > b.max.x) - { - return false; - } + entry.x = b.max.x; + entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); + entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); + } + } + else if (r.pos.x < b.min.x || r.pos.x > b.max.x) + { + return false; + } } // @@ -574,73 +575,73 @@ findEntryAndExitPoints (const Line3 &r, if (r.dir.y >= 0) { - T d1 = b.max.y - r.pos.y; - T d2 = b.min.y - r.pos.y; - - if (r.dir.y > 1 || - (abs (d1) < TMAX * r.dir.y && - abs (d2) < TMAX * r.dir.y)) - { - T t1 = d1 / r.dir.y; - T t2 = d2 / r.dir.y; - - if (tBackMin > t1) - { - tBackMin = t1; - - exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); - exit.y = b.max.y; - exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); - } - - if (tFrontMax < t2) - { - tFrontMax = t2; - - entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); - entry.y = b.min.y; - entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); - } - } - else if (r.pos.y < b.min.y || r.pos.y > b.max.y) - { - return false; - } + T d1 = b.max.y - r.pos.y; + T d2 = b.min.y - r.pos.y; + + if (r.dir.y > 1 || + (abs (d1) < TMAX * r.dir.y && + abs (d2) < TMAX * r.dir.y)) + { + T t1 = d1 / r.dir.y; + T t2 = d2 / r.dir.y; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); + exit.y = b.max.y; + exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); + entry.y = b.min.y; + entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); + } + } + else if (r.pos.y < b.min.y || r.pos.y > b.max.y) + { + return false; + } } else // r.dir.y < 0 { - T d1 = b.min.y - r.pos.y; - T d2 = b.max.y - r.pos.y; + T d1 = b.min.y - r.pos.y; + T d2 = b.max.y - r.pos.y; - if (r.dir.y < -1 || - (abs (d1) < -TMAX * r.dir.y && - abs (d2) < -TMAX * r.dir.y)) - { - T t1 = d1 / r.dir.y; - T t2 = d2 / r.dir.y; + if (r.dir.y < -1 || + (abs (d1) < -TMAX * r.dir.y && + abs (d2) < -TMAX * r.dir.y)) + { + T t1 = d1 / r.dir.y; + T t2 = d2 / r.dir.y; - if (tBackMin > t1) - { - tBackMin = t1; + if (tBackMin > t1) + { + tBackMin = t1; - exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); - exit.y = b.min.y; - exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); - } + exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); + exit.y = b.min.y; + exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); + } - if (tFrontMax < t2) - { - tFrontMax = t2; + if (tFrontMax < t2) + { + tFrontMax = t2; - entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); - entry.y = b.max.y; - entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); - } - } - else if (r.pos.y < b.min.y || r.pos.y > b.max.y) - { - return false; - } + entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); + entry.y = b.max.y; + entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); + } + } + else if (r.pos.y < b.min.y || r.pos.y > b.max.y) + { + return false; + } } // @@ -649,73 +650,73 @@ findEntryAndExitPoints (const Line3 &r, if (r.dir.z >= 0) { - T d1 = b.max.z - r.pos.z; - T d2 = b.min.z - r.pos.z; - - if (r.dir.z > 1 || - (abs (d1) < TMAX * r.dir.z && - abs (d2) < TMAX * r.dir.z)) - { - T t1 = d1 / r.dir.z; - T t2 = d2 / r.dir.z; - - if (tBackMin > t1) - { - tBackMin = t1; - - exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); - exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); - exit.z = b.max.z; - } - - if (tFrontMax < t2) - { - tFrontMax = t2; - - entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); - entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); - entry.z = b.min.z; - } - } - else if (r.pos.z < b.min.z || r.pos.z > b.max.z) - { - return false; - } + T d1 = b.max.z - r.pos.z; + T d2 = b.min.z - r.pos.z; + + if (r.dir.z > 1 || + (abs (d1) < TMAX * r.dir.z && + abs (d2) < TMAX * r.dir.z)) + { + T t1 = d1 / r.dir.z; + T t2 = d2 / r.dir.z; + + if (tBackMin > t1) + { + tBackMin = t1; + + exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); + exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); + exit.z = b.max.z; + } + + if (tFrontMax < t2) + { + tFrontMax = t2; + + entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); + entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); + entry.z = b.min.z; + } + } + else if (r.pos.z < b.min.z || r.pos.z > b.max.z) + { + return false; + } } else // r.dir.z < 0 { - T d1 = b.min.z - r.pos.z; - T d2 = b.max.z - r.pos.z; + T d1 = b.min.z - r.pos.z; + T d2 = b.max.z - r.pos.z; - if (r.dir.z < -1 || - (abs (d1) < -TMAX * r.dir.z && - abs (d2) < -TMAX * r.dir.z)) - { - T t1 = d1 / r.dir.z; - T t2 = d2 / r.dir.z; + if (r.dir.z < -1 || + (abs (d1) < -TMAX * r.dir.z && + abs (d2) < -TMAX * r.dir.z)) + { + T t1 = d1 / r.dir.z; + T t2 = d2 / r.dir.z; - if (tBackMin > t1) - { - tBackMin = t1; + if (tBackMin > t1) + { + tBackMin = t1; - exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); - exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); - exit.z = b.min.z; - } + exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); + exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); + exit.z = b.min.z; + } - if (tFrontMax < t2) - { - tFrontMax = t2; + if (tFrontMax < t2) + { + tFrontMax = t2; - entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); - entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); - entry.z = b.max.z; - } - } - else if (r.pos.z < b.min.z || r.pos.z > b.max.z) - { - return false; - } + entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); + entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); + entry.z = b.max.z; + } + } + else if (r.pos.z < b.min.z || r.pos.z > b.max.z) + { + return false; + } } return tFrontMax <= tBackMin; @@ -752,21 +753,21 @@ intersects (const Box< Vec3 > &b, const Line3 &r, Vec3 &ip) if (b.isEmpty()) { - // - // No ray intersects an empty box - // + // + // No ray intersects an empty box + // - return false; + return false; } if (b.intersects (r.pos)) { - // - // The ray starts inside the box - // + // + // The ray starts inside the box + // - ip = r.pos; - return true; + ip = r.pos; + return true; } // @@ -793,68 +794,68 @@ intersects (const Box< Vec3 > &b, const Line3 &r, Vec3 &ip) if (r.dir.x > 0) { - if (r.pos.x > b.max.x) - return false; + if (r.pos.x > b.max.x) + return false; - T d = b.max.x - r.pos.x; + T d = b.max.x - r.pos.x; - if (r.dir.x > 1 || d < TMAX * r.dir.x) - { - T t = d / r.dir.x; + if (r.dir.x > 1 || d < TMAX * r.dir.x) + { + T t = d / r.dir.x; - if (tBackMin > t) - tBackMin = t; - } + if (tBackMin > t) + tBackMin = t; + } - if (r.pos.x <= b.min.x) - { - T d = b.min.x - r.pos.x; - T t = (r.dir.x > 1 || d < TMAX * r.dir.x)? d / r.dir.x: TMAX; + if (r.pos.x <= b.min.x) + { + T d = b.min.x - r.pos.x; + T t = (r.dir.x > 1 || d < TMAX * r.dir.x)? d / r.dir.x: TMAX; - if (tFrontMax < t) - { - tFrontMax = t; + if (tFrontMax < t) + { + tFrontMax = t; - ip.x = b.min.x; - ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); - ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); - } - } + ip.x = b.min.x; + ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); + ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); + } + } } else if (r.dir.x < 0) { - if (r.pos.x < b.min.x) - return false; + if (r.pos.x < b.min.x) + return false; - T d = b.min.x - r.pos.x; + T d = b.min.x - r.pos.x; - if (r.dir.x < -1 || d > TMAX * r.dir.x) - { - T t = d / r.dir.x; + if (r.dir.x < -1 || d > TMAX * r.dir.x) + { + T t = d / r.dir.x; - if (tBackMin > t) - tBackMin = t; - } + if (tBackMin > t) + tBackMin = t; + } - if (r.pos.x >= b.max.x) - { - T d = b.max.x - r.pos.x; - T t = (r.dir.x < -1 || d > TMAX * r.dir.x)? d / r.dir.x: TMAX; + if (r.pos.x >= b.max.x) + { + T d = b.max.x - r.pos.x; + T t = (r.dir.x < -1 || d > TMAX * r.dir.x)? d / r.dir.x: TMAX; - if (tFrontMax < t) - { - tFrontMax = t; + if (tFrontMax < t) + { + tFrontMax = t; - ip.x = b.max.x; - ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); - ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); - } - } + ip.x = b.max.x; + ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); + ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); + } + } } else // r.dir.x == 0 { - if (r.pos.x < b.min.x || r.pos.x > b.max.x) - return false; + if (r.pos.x < b.min.x || r.pos.x > b.max.x) + return false; } // @@ -863,68 +864,68 @@ intersects (const Box< Vec3 > &b, const Line3 &r, Vec3 &ip) if (r.dir.y > 0) { - if (r.pos.y > b.max.y) - return false; + if (r.pos.y > b.max.y) + return false; - T d = b.max.y - r.pos.y; + T d = b.max.y - r.pos.y; - if (r.dir.y > 1 || d < TMAX * r.dir.y) - { - T t = d / r.dir.y; + if (r.dir.y > 1 || d < TMAX * r.dir.y) + { + T t = d / r.dir.y; - if (tBackMin > t) - tBackMin = t; - } + if (tBackMin > t) + tBackMin = t; + } - if (r.pos.y <= b.min.y) - { - T d = b.min.y - r.pos.y; - T t = (r.dir.y > 1 || d < TMAX * r.dir.y)? d / r.dir.y: TMAX; + if (r.pos.y <= b.min.y) + { + T d = b.min.y - r.pos.y; + T t = (r.dir.y > 1 || d < TMAX * r.dir.y)? d / r.dir.y: TMAX; - if (tFrontMax < t) - { - tFrontMax = t; + if (tFrontMax < t) + { + tFrontMax = t; - ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); - ip.y = b.min.y; - ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); - } - } + ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); + ip.y = b.min.y; + ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); + } + } } else if (r.dir.y < 0) { - if (r.pos.y < b.min.y) - return false; + if (r.pos.y < b.min.y) + return false; - T d = b.min.y - r.pos.y; + T d = b.min.y - r.pos.y; - if (r.dir.y < -1 || d > TMAX * r.dir.y) - { - T t = d / r.dir.y; + if (r.dir.y < -1 || d > TMAX * r.dir.y) + { + T t = d / r.dir.y; - if (tBackMin > t) - tBackMin = t; - } + if (tBackMin > t) + tBackMin = t; + } - if (r.pos.y >= b.max.y) - { - T d = b.max.y - r.pos.y; - T t = (r.dir.y < -1 || d > TMAX * r.dir.y)? d / r.dir.y: TMAX; + if (r.pos.y >= b.max.y) + { + T d = b.max.y - r.pos.y; + T t = (r.dir.y < -1 || d > TMAX * r.dir.y)? d / r.dir.y: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; - if (tFrontMax < t) - { - tFrontMax = t; - - ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); - ip.y = b.max.y; - ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); - } - } + ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); + ip.y = b.max.y; + ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); + } + } } else // r.dir.y == 0 { - if (r.pos.y < b.min.y || r.pos.y > b.max.y) - return false; + if (r.pos.y < b.min.y || r.pos.y > b.max.y) + return false; } // @@ -933,68 +934,68 @@ intersects (const Box< Vec3 > &b, const Line3 &r, Vec3 &ip) if (r.dir.z > 0) { - if (r.pos.z > b.max.z) - return false; + if (r.pos.z > b.max.z) + return false; - T d = b.max.z - r.pos.z; + T d = b.max.z - r.pos.z; - if (r.dir.z > 1 || d < TMAX * r.dir.z) - { - T t = d / r.dir.z; + if (r.dir.z > 1 || d < TMAX * r.dir.z) + { + T t = d / r.dir.z; - if (tBackMin > t) - tBackMin = t; - } + if (tBackMin > t) + tBackMin = t; + } - if (r.pos.z <= b.min.z) - { - T d = b.min.z - r.pos.z; - T t = (r.dir.z > 1 || d < TMAX * r.dir.z)? d / r.dir.z: TMAX; - - if (tFrontMax < t) - { - tFrontMax = t; + if (r.pos.z <= b.min.z) + { + T d = b.min.z - r.pos.z; + T t = (r.dir.z > 1 || d < TMAX * r.dir.z)? d / r.dir.z: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; - ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); - ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); - ip.z = b.min.z; - } - } + ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); + ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); + ip.z = b.min.z; + } + } } else if (r.dir.z < 0) { - if (r.pos.z < b.min.z) - return false; + if (r.pos.z < b.min.z) + return false; - T d = b.min.z - r.pos.z; + T d = b.min.z - r.pos.z; - if (r.dir.z < -1 || d > TMAX * r.dir.z) - { - T t = d / r.dir.z; + if (r.dir.z < -1 || d > TMAX * r.dir.z) + { + T t = d / r.dir.z; - if (tBackMin > t) - tBackMin = t; - } + if (tBackMin > t) + tBackMin = t; + } - if (r.pos.z >= b.max.z) - { - T d = b.max.z - r.pos.z; - T t = (r.dir.z < -1 || d > TMAX * r.dir.z)? d / r.dir.z: TMAX; + if (r.pos.z >= b.max.z) + { + T d = b.max.z - r.pos.z; + T t = (r.dir.z < -1 || d > TMAX * r.dir.z)? d / r.dir.z: TMAX; + + if (tFrontMax < t) + { + tFrontMax = t; - if (tFrontMax < t) - { - tFrontMax = t; - - ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); - ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); - ip.z = b.max.z; - } - } + ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); + ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); + ip.z = b.max.z; + } + } } else // r.dir.z == 0 { - if (r.pos.z < b.min.z || r.pos.z > b.max.z) - return false; + if (r.pos.z < b.min.z || r.pos.z > b.max.z) + return false; } return tFrontMax <= tBackMin; @@ -1010,6 +1011,6 @@ intersects (const Box< Vec3 > &box, const Line3 &ray) } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHBOXALGO_H diff --git a/3rdparty/openexr/Imath/ImathColor.h b/3rdparty/openexr/Imath/ImathColor.h index 088653e87e..743c72d143 100644 --- a/3rdparty/openexr/Imath/ImathColor.h +++ b/3rdparty/openexr/Imath/ImathColor.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,9 +44,10 @@ //---------------------------------------------------- #include "ImathVec.h" +#include "ImathNamespace.h" #include "half.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template @@ -340,7 +341,7 @@ Color3::operator += (const Color3 &c) } template -inline Color3 +inline Color3 Color3::operator + (const Color3 &c) const { return Color3 (*(Vec3 *)this + (const Vec3 &)c); @@ -355,14 +356,14 @@ Color3::operator -= (const Color3 &c) } template -inline Color3 +inline Color3 Color3::operator - (const Color3 &c) const { return Color3 (*(Vec3 *)this - (const Vec3 &)c); } template -inline Color3 +inline Color3 Color3::operator - () const { return Color3 (-(*(Vec3 *)this)); @@ -393,14 +394,14 @@ Color3::operator *= (T a) } template -inline Color3 +inline Color3 Color3::operator * (const Color3 &c) const { return Color3 (*(Vec3 *)this * (const Vec3 &)c); } template -inline Color3 +inline Color3 Color3::operator * (T a) const { return Color3 (*(Vec3 *)this * a); @@ -423,14 +424,14 @@ Color3::operator /= (T a) } template -inline Color3 +inline Color3 Color3::operator / (const Color3 &c) const { return Color3 (*(Vec3 *)this / (const Vec3 &)c); } template -inline Color3 +inline Color3 Color3::operator / (T a) const { return Color3 (*(Vec3 *)this / a); @@ -729,6 +730,7 @@ operator * (S x, const Color4 &v) return Color4 (x * v.r, x * v.g, x * v.b, x * v.a); } -} // namespace Imath -#endif +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHCOLOR_H diff --git a/3rdparty/openexr/Imath/ImathColorAlgo.cpp b/3rdparty/openexr/Imath/ImathColorAlgo.cpp index 9c8ecac037..a351c40e21 100644 --- a/3rdparty/openexr/Imath/ImathColorAlgo.cpp +++ b/3rdparty/openexr/Imath/ImathColorAlgo.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,7 +41,7 @@ #include "ImathColorAlgo.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER Vec3 @@ -52,7 +52,7 @@ hsv2rgb_d(const Vec3 &hsv) double val = hsv.z; double x = 0.0, y = 0.0, z = 0.0; - + if (hue == 1) hue = 0; else hue *= 6; @@ -62,7 +62,7 @@ hsv2rgb_d(const Vec3 &hsv) double q = val*(1-(sat*f)); double t = val*(1-(sat*(1-f))); - switch (i) + switch (i) { case 0: x = val; y = t; z = p; break; case 1: x = q; y = val; z = p; break; @@ -76,7 +76,7 @@ hsv2rgb_d(const Vec3 &hsv) } -Color4 +Color4 hsv2rgb_d(const Color4 &hsv) { double hue = hsv.r; @@ -84,7 +84,7 @@ hsv2rgb_d(const Color4 &hsv) double val = hsv.b; double r = 0.0, g = 0.0, b = 0.0; - + if (hue == 1) hue = 0; else hue *= 6; @@ -94,7 +94,7 @@ hsv2rgb_d(const Color4 &hsv) double q = val*(1-(sat*f)); double t = val*(1-(sat*(1-f))); - switch (i) + switch (i) { case 0: r = val; g = t; b = p; break; case 1: r = q; g = val; b = p; break; @@ -122,21 +122,21 @@ rgb2hsv_d(const Vec3 &c) double val = max; double sat = 0; double hue = 0; - + if (max != 0) sat = range/max; - - if (sat != 0) + + if (sat != 0) { - double h; - - if (x == max) h = (y - z) / range; - else if (y == max) h = 2 + (z - x) / range; - else h = 4 + (x - y) / range; - - hue = h/6.; - - if (hue < 0.) - hue += 1.0; + double h; + + if (x == max) h = (y - z) / range; + else if (y == max) h = 2 + (z - x) / range; + else h = 4 + (x - y) / range; + + hue = h/6.; + + if (hue < 0.) + hue += 1.0; } return Vec3(hue,sat,val); } @@ -155,24 +155,24 @@ rgb2hsv_d(const Color4 &c) double val = max; double sat = 0; double hue = 0; - + if (max != 0) sat = range/max; - - if (sat != 0) + + if (sat != 0) { - double h; - - if (r == max) h = (g - b) / range; - else if (g == max) h = 2 + (b - r) / range; - else h = 4 + (r - g) / range; - - hue = h/6.; - - if (hue < 0.) - hue += 1.0; + double h; + + if (r == max) h = (g - b) / range; + else if (g == max) h = 2 + (b - r) / range; + else h = 4 + (r - g) / range; + + hue = h/6.; + + if (hue < 0.) + hue += 1.0; } return Color4(hue,sat,val,c.a); } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/Imath/ImathColorAlgo.h b/3rdparty/openexr/Imath/ImathColorAlgo.h index 0e8ad28ba7..cbc3be4550 100644 --- a/3rdparty/openexr/Imath/ImathColorAlgo.h +++ b/3rdparty/openexr/Imath/ImathColorAlgo.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,10 +39,12 @@ #include "ImathColor.h" +#include "ImathExport.h" #include "ImathMath.h" #include "ImathLimits.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER // @@ -50,14 +52,13 @@ namespace Imath { // These routines eliminate type warnings under g++. // -Vec3 hsv2rgb_d(const Vec3 &hsv); - -Color4 hsv2rgb_d(const Color4 &hsv); +IMATH_EXPORT Vec3 hsv2rgb_d(const Vec3 &hsv); +IMATH_EXPORT Color4 hsv2rgb_d(const Color4 &hsv); -Vec3 rgb2hsv_d(const Vec3 &rgb); +IMATH_EXPORT Vec3 rgb2hsv_d(const Vec3 &rgb); -Color4 rgb2hsv_d(const Color4 &rgb); +IMATH_EXPORT Color4 rgb2hsv_d(const Color4 &rgb); // @@ -67,98 +68,98 @@ Color4 rgb2hsv_d(const Color4 &rgb); // see each funtion definition for details. // -template -Vec3 +template +Vec3 hsv2rgb(const Vec3 &hsv) { if ( limits::isIntegral() ) { - Vec3 v = Vec3(hsv.x / double(limits::max()), - hsv.y / double(limits::max()), - hsv.z / double(limits::max())); - Vec3 c = hsv2rgb_d(v); - return Vec3((T) (c.x * limits::max()), - (T) (c.y * limits::max()), - (T) (c.z * limits::max())); + Vec3 v = Vec3(hsv.x / double(limits::max()), + hsv.y / double(limits::max()), + hsv.z / double(limits::max())); + Vec3 c = hsv2rgb_d(v); + return Vec3((T) (c.x * limits::max()), + (T) (c.y * limits::max()), + (T) (c.z * limits::max())); } else { - Vec3 v = Vec3(hsv.x, hsv.y, hsv.z); - Vec3 c = hsv2rgb_d(v); - return Vec3((T) c.x, (T) c.y, (T) c.z); + Vec3 v = Vec3(hsv.x, hsv.y, hsv.z); + Vec3 c = hsv2rgb_d(v); + return Vec3((T) c.x, (T) c.y, (T) c.z); } } -template -Color4 +template +Color4 hsv2rgb(const Color4 &hsv) { if ( limits::isIntegral() ) { - Color4 v = Color4(hsv.r / float(limits::max()), - hsv.g / float(limits::max()), - hsv.b / float(limits::max()), - hsv.a / float(limits::max())); - Color4 c = hsv2rgb_d(v); - return Color4((T) (c.r * limits::max()), - (T) (c.g * limits::max()), - (T) (c.b * limits::max()), - (T) (c.a * limits::max())); + Color4 v = Color4(hsv.r / float(limits::max()), + hsv.g / float(limits::max()), + hsv.b / float(limits::max()), + hsv.a / float(limits::max())); + Color4 c = hsv2rgb_d(v); + return Color4((T) (c.r * limits::max()), + (T) (c.g * limits::max()), + (T) (c.b * limits::max()), + (T) (c.a * limits::max())); } else { - Color4 v = Color4(hsv.r, hsv.g, hsv.b, hsv.a); - Color4 c = hsv2rgb_d(v); - return Color4((T) c.r, (T) c.g, (T) c.b, (T) c.a); + Color4 v = Color4(hsv.r, hsv.g, hsv.b, hsv.a); + Color4 c = hsv2rgb_d(v); + return Color4((T) c.r, (T) c.g, (T) c.b, (T) c.a); } } -template -Vec3 +template +Vec3 rgb2hsv(const Vec3 &rgb) { if ( limits::isIntegral() ) { - Vec3 v = Vec3(rgb.x / double(limits::max()), - rgb.y / double(limits::max()), - rgb.z / double(limits::max())); - Vec3 c = rgb2hsv_d(v); - return Vec3((T) (c.x * limits::max()), - (T) (c.y * limits::max()), - (T) (c.z * limits::max())); + Vec3 v = Vec3(rgb.x / double(limits::max()), + rgb.y / double(limits::max()), + rgb.z / double(limits::max())); + Vec3 c = rgb2hsv_d(v); + return Vec3((T) (c.x * limits::max()), + (T) (c.y * limits::max()), + (T) (c.z * limits::max())); } else { - Vec3 v = Vec3(rgb.x, rgb.y, rgb.z); - Vec3 c = rgb2hsv_d(v); - return Vec3((T) c.x, (T) c.y, (T) c.z); + Vec3 v = Vec3(rgb.x, rgb.y, rgb.z); + Vec3 c = rgb2hsv_d(v); + return Vec3((T) c.x, (T) c.y, (T) c.z); } } -template -Color4 +template +Color4 rgb2hsv(const Color4 &rgb) { if ( limits::isIntegral() ) { - Color4 v = Color4(rgb.r / float(limits::max()), - rgb.g / float(limits::max()), - rgb.b / float(limits::max()), - rgb.a / float(limits::max())); - Color4 c = rgb2hsv_d(v); - return Color4((T) (c.r * limits::max()), - (T) (c.g * limits::max()), - (T) (c.b * limits::max()), - (T) (c.a * limits::max())); + Color4 v = Color4(rgb.r / float(limits::max()), + rgb.g / float(limits::max()), + rgb.b / float(limits::max()), + rgb.a / float(limits::max())); + Color4 c = rgb2hsv_d(v); + return Color4((T) (c.r * limits::max()), + (T) (c.g * limits::max()), + (T) (c.b * limits::max()), + (T) (c.a * limits::max())); } else { - Color4 v = Color4(rgb.r, rgb.g, rgb.b, rgb.a); - Color4 c = rgb2hsv_d(v); - return Color4((T) c.r, (T) c.g, (T) c.b, (T) c.a); + Color4 v = Color4(rgb.r, rgb.g, rgb.b, rgb.a); + Color4 c = rgb2hsv_d(v); + return Color4((T) c.r, (T) c.g, (T) c.b, (T) c.a); } } @@ -168,16 +169,16 @@ rgb2packed(const Vec3 &c) { if ( limits::isIntegral() ) { - float x = c.x / float(limits::max()); - float y = c.y / float(limits::max()); - float z = c.z / float(limits::max()); - return rgb2packed( V3f(x,y,z) ); + float x = c.x / float(limits::max()); + float y = c.y / float(limits::max()); + float z = c.z / float(limits::max()); + return rgb2packed( V3f(x,y,z) ); } else { - return ( (PackedColor) (c.x * 255) | - (((PackedColor) (c.y * 255)) << 8) | - (((PackedColor) (c.z * 255)) << 16) | 0xFF000000 ); + return ( (PackedColor) (c.x * 255) | + (((PackedColor) (c.y * 255)) << 8) | + (((PackedColor) (c.z * 255)) << 16) | 0xFF000000 ); } } @@ -187,18 +188,18 @@ rgb2packed(const Color4 &c) { if ( limits::isIntegral() ) { - float r = c.r / float(limits::max()); - float g = c.g / float(limits::max()); - float b = c.b / float(limits::max()); - float a = c.a / float(limits::max()); - return rgb2packed( C4f(r,g,b,a) ); + float r = c.r / float(limits::max()); + float g = c.g / float(limits::max()); + float b = c.b / float(limits::max()); + float a = c.a / float(limits::max()); + return rgb2packed( C4f(r,g,b,a) ); } else { - return ( (PackedColor) (c.r * 255) | - (((PackedColor) (c.g * 255)) << 8) | - (((PackedColor) (c.b * 255)) << 16) | - (((PackedColor) (c.a * 255)) << 24)); + return ( (PackedColor) (c.r * 255) | + (((PackedColor) (c.g * 255)) << 8) | + (((PackedColor) (c.b * 255)) << 16) | + (((PackedColor) (c.a * 255)) << 24)); } } @@ -214,17 +215,17 @@ packed2rgb(PackedColor packed, Vec3 &out) { if ( limits::isIntegral() ) { - T f = limits::max() / ((PackedColor)0xFF); - out.x = (packed & 0xFF) * f; - out.y = ((packed & 0xFF00) >> 8) * f; - out.z = ((packed & 0xFF0000) >> 16) * f; + T f = limits::max() / ((PackedColor)0xFF); + out.x = (packed & 0xFF) * f; + out.y = ((packed & 0xFF00) >> 8) * f; + out.z = ((packed & 0xFF0000) >> 16) * f; } else { - T f = T(1) / T(255); - out.x = (packed & 0xFF) * f; - out.y = ((packed & 0xFF00) >> 8) * f; - out.z = ((packed & 0xFF0000) >> 16) * f; + T f = T(1) / T(255); + out.x = (packed & 0xFF) * f; + out.y = ((packed & 0xFF00) >> 8) * f; + out.z = ((packed & 0xFF0000) >> 16) * f; } } @@ -234,23 +235,23 @@ packed2rgb(PackedColor packed, Color4 &out) { if ( limits::isIntegral() ) { - T f = limits::max() / ((PackedColor)0xFF); - out.r = (packed & 0xFF) * f; - out.g = ((packed & 0xFF00) >> 8) * f; - out.b = ((packed & 0xFF0000) >> 16) * f; - out.a = ((packed & 0xFF000000) >> 24) * f; + T f = limits::max() / ((PackedColor)0xFF); + out.r = (packed & 0xFF) * f; + out.g = ((packed & 0xFF00) >> 8) * f; + out.b = ((packed & 0xFF0000) >> 16) * f; + out.a = ((packed & 0xFF000000) >> 24) * f; } else { - T f = T(1) / T(255); - out.r = (packed & 0xFF) * f; - out.g = ((packed & 0xFF00) >> 8) * f; - out.b = ((packed & 0xFF0000) >> 16) * f; - out.a = ((packed & 0xFF000000) >> 24) * f; + T f = T(1) / T(255); + out.r = (packed & 0xFF) * f; + out.g = ((packed & 0xFF00) >> 8) * f; + out.b = ((packed & 0xFF0000) >> 16) * f; + out.a = ((packed & 0xFF000000) >> 24) * f; } } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHCOLORALGO_H diff --git a/3rdparty/openexr/Imath/ImathEuler.h b/3rdparty/openexr/Imath/ImathEuler.h index ffb144dafe..6b2b39e692 100644 --- a/3rdparty/openexr/Imath/ImathEuler.h +++ b/3rdparty/openexr/Imath/ImathEuler.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -51,7 +51,7 @@ // There are 24 possible combonations of Euler angle // representations of which 12 are common in CG and you will // probably only use 6 of these which in this scheme are the -// non-relative-non-repeating types. +// non-relative-non-repeating types. // // The representations can be partitioned according to two // criteria: @@ -66,7 +66,7 @@ // When you construct a given representation from scratch you // must order the angles according to their priorities. So, the // easiest is a softimage or aerospace (yaw/pitch/roll) ordering -// of ZYX. +// of ZYX. // // float x_rot = 1; // float y_rot = 2; @@ -106,19 +106,19 @@ // If you want to set the Euler with an XYZVector use the // optional layout argument: // -// Eulerf angles(x_rot, y_rot, z_rot, +// Eulerf angles(x_rot, y_rot, z_rot, // Eulerf::YXZ, // Eulerf::XYZLayout); // // This is the same as: // // Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ); -// +// // Note that this won't do anything intelligent if you have a // repeated axis in the euler angles (e.g. XYX) // // If you need to use the "relative" versions of these, you will -// need to use the "r" enums. +// need to use the "r" enums. // // The units of the rotation angles are assumed to be radians. // @@ -130,9 +130,11 @@ #include "ImathQuat.h" #include "ImathMatrix.h" #include "ImathLimits.h" +#include "ImathNamespace.h" + #include -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // Disable MS VC++ warnings about conversion from double to float @@ -143,61 +145,61 @@ template class Euler : public Vec3 { public: - + using Vec3::x; using Vec3::y; using Vec3::z; enum Order { - // - // All 24 possible orderings - // - - XYZ = 0x0101, // "usual" orderings - XZY = 0x0001, - YZX = 0x1101, - YXZ = 0x1001, - ZXY = 0x2101, - ZYX = 0x2001, - - XZX = 0x0011, // first axis repeated - XYX = 0x0111, - YXY = 0x1011, - YZY = 0x1111, - ZYZ = 0x2011, - ZXZ = 0x2111, - - XYZr = 0x2000, // relative orderings -- not common - XZYr = 0x2100, - YZXr = 0x1000, - YXZr = 0x1100, - ZXYr = 0x0000, - ZYXr = 0x0100, - - XZXr = 0x2110, // relative first axis repeated - XYXr = 0x2010, - YXYr = 0x1110, - YZYr = 0x1010, - ZYZr = 0x0110, - ZXZr = 0x0010, - // |||| - // VVVV - // Legend: ABCD - // A -> Initial Axis (0==x, 1==y, 2==z) - // B -> Parity Even (1==true) - // C -> Initial Repeated (1==true) - // D -> Frame Static (1==true) - // - - Legal = XYZ | XZY | YZX | YXZ | ZXY | ZYX | - XZX | XYX | YXY | YZY | ZYZ | ZXZ | - XYZr| XZYr| YZXr| YXZr| ZXYr| ZYXr| - XZXr| XYXr| YXYr| YZYr| ZYZr| ZXZr, - - Min = 0x0000, - Max = 0x2111, - Default = XYZ + // + // All 24 possible orderings + // + + XYZ = 0x0101, // "usual" orderings + XZY = 0x0001, + YZX = 0x1101, + YXZ = 0x1001, + ZXY = 0x2101, + ZYX = 0x2001, + + XZX = 0x0011, // first axis repeated + XYX = 0x0111, + YXY = 0x1011, + YZY = 0x1111, + ZYZ = 0x2011, + ZXZ = 0x2111, + + XYZr = 0x2000, // relative orderings -- not common + XZYr = 0x2100, + YZXr = 0x1000, + YXZr = 0x1100, + ZXYr = 0x0000, + ZYXr = 0x0100, + + XZXr = 0x2110, // relative first axis repeated + XYXr = 0x2010, + YXYr = 0x1110, + YZYr = 0x1010, + ZYZr = 0x0110, + ZXZr = 0x0010, + // |||| + // VVVV + // Legend: ABCD + // A -> Initial Axis (0==x, 1==y, 2==z) + // B -> Parity Even (1==true) + // C -> Initial Repeated (1==true) + // D -> Frame Static (1==true) + // + + Legal = XYZ | XZY | YZX | YXZ | ZXY | ZYX | + XZX | XYX | YXY | YZY | ZYZ | ZXZ | + XYZr| XZYr| YZXr| YXZr| ZXYr| ZYXr| + XZXr| XYXr| YXYr| YZYr| ZYZr| ZXZr, + + Min = 0x0000, + Max = 0x2111, + Default = XYZ }; enum Axis { X = 0, Y = 1, Z = 2 }; @@ -233,7 +235,7 @@ class Euler : public Vec3 //-------------------------------------------------------- // Set the euler value - // This does NOT convert the angles, but setXYZVector() + // This does NOT convert the angles, but setXYZVector() // does reorder the input vector. //-------------------------------------------------------- @@ -245,9 +247,9 @@ class Euler : public Vec3 void setOrder(Order); void set(Axis initial, - bool relative, - bool parityEven, - bool firstRepeats); + bool relative, + bool parityEven, + bool firstRepeats); //------------------------------------------------------------ // Conversions, toXYZVector() reorders the angles so that @@ -282,7 +284,7 @@ class Euler : public Vec3 // Use this function to determine mapping from xyz to ijk // - reshuffles the xyz to match the order //--------------------------------------------------- - + void angleMapping(int &i, int &j, int &k) const; //---------------------------------------------------------------------- @@ -311,10 +313,10 @@ class Euler : public Vec3 static float angleMod (T angle); static void simpleXYZRotation (Vec3 &xyzRot, - const Vec3 &targetXyzRot); + const Vec3 &targetXyzRot); static void nearestRotation (Vec3 &xyzRot, - const Vec3 &targetXyzRot, - Order order = XYZ); + const Vec3 &targetXyzRot, + Order order = XYZ); void makeNear (const Euler &target); @@ -413,11 +415,11 @@ Euler::Euler(typename Euler::Order p) : } template -inline Euler::Euler( const Vec3 &v, - typename Euler::Order p, - typename Euler::InputLayout l ) +inline Euler::Euler( const Vec3 &v, + typename Euler::Order p, + typename Euler::InputLayout l ) { - setOrder(p); + setOrder(p); if ( l == XYZLayout ) setXYZVector(v); else { x = v.x; y = v.y; z = v.z; } } @@ -437,9 +439,9 @@ inline Euler::Euler(const Euler &euler,Order p) } template -inline Euler::Euler( T xi, T yi, T zi, - typename Euler::Order p, - typename Euler::InputLayout l) +inline Euler::Euler( T xi, T yi, T zi, + typename Euler::Order p, + typename Euler::InputLayout l) { setOrder(p); if ( l == XYZLayout ) setXYZVector(Vec3(xi,yi,zi)); @@ -474,77 +476,77 @@ void Euler::extract(const Matrix33 &M) if (_initialRepeated) { - // - // Extract the first angle, x. - // - - x = Math::atan2 (M[j][i], M[k][i]); - - // - // Remove the x rotation from M, so that the remaining - // rotation, N, is only around two axes, and gimbal lock - // cannot occur. - // - - Vec3 r (0, 0, 0); - r[i] = (_parityEven? -x: x); - - Matrix44 N; - N.rotate (r); - - N = N * Matrix44 (M[0][0], M[0][1], M[0][2], 0, - M[1][0], M[1][1], M[1][2], 0, - M[2][0], M[2][1], M[2][2], 0, - 0, 0, 0, 1); - // - // Extract the other two angles, y and z, from N. - // - - T sy = Math::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]); - y = Math::atan2 (sy, N[i][i]); - z = Math::atan2 (N[j][k], N[j][j]); + // + // Extract the first angle, x. + // + + x = Math::atan2 (M[j][i], M[k][i]); + + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // + + Vec3 r (0, 0, 0); + r[i] = (_parityEven? -x: x); + + Matrix44 N; + N.rotate (r); + + N = N * Matrix44 (M[0][0], M[0][1], M[0][2], 0, + M[1][0], M[1][1], M[1][2], 0, + M[2][0], M[2][1], M[2][2], 0, + 0, 0, 0, 1); + // + // Extract the other two angles, y and z, from N. + // + + T sy = Math::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]); + y = Math::atan2 (sy, N[i][i]); + z = Math::atan2 (N[j][k], N[j][j]); } else { - // - // Extract the first angle, x. - // - - x = Math::atan2 (M[j][k], M[k][k]); - - // - // Remove the x rotation from M, so that the remaining - // rotation, N, is only around two axes, and gimbal lock - // cannot occur. - // - - Vec3 r (0, 0, 0); - r[i] = (_parityEven? -x: x); - - Matrix44 N; - N.rotate (r); - - N = N * Matrix44 (M[0][0], M[0][1], M[0][2], 0, - M[1][0], M[1][1], M[1][2], 0, - M[2][0], M[2][1], M[2][2], 0, - 0, 0, 0, 1); - // - // Extract the other two angles, y and z, from N. - // - - T cy = Math::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]); - y = Math::atan2 (-N[i][k], cy); - z = Math::atan2 (-N[j][i], N[j][j]); + // + // Extract the first angle, x. + // + + x = Math::atan2 (M[j][k], M[k][k]); + + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // + + Vec3 r (0, 0, 0); + r[i] = (_parityEven? -x: x); + + Matrix44 N; + N.rotate (r); + + N = N * Matrix44 (M[0][0], M[0][1], M[0][2], 0, + M[1][0], M[1][1], M[1][2], 0, + M[2][0], M[2][1], M[2][2], 0, + 0, 0, 0, 1); + // + // Extract the other two angles, y and z, from N. + // + + T cy = Math::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]); + y = Math::atan2 (-N[i][k], cy); + z = Math::atan2 (-N[j][i], N[j][j]); } if (!_parityEven) - *this *= -1; + *this *= -1; if (!_frameStatic) { - T t = x; - x = z; - z = t; + T t = x; + x = z; + z = t; } } @@ -556,71 +558,71 @@ void Euler::extract(const Matrix44 &M) if (_initialRepeated) { - // - // Extract the first angle, x. - // + // + // Extract the first angle, x. + // - x = Math::atan2 (M[j][i], M[k][i]); + x = Math::atan2 (M[j][i], M[k][i]); - // - // Remove the x rotation from M, so that the remaining - // rotation, N, is only around two axes, and gimbal lock - // cannot occur. - // + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // - Vec3 r (0, 0, 0); - r[i] = (_parityEven? -x: x); + Vec3 r (0, 0, 0); + r[i] = (_parityEven? -x: x); - Matrix44 N; - N.rotate (r); - N = N * M; + Matrix44 N; + N.rotate (r); + N = N * M; - // - // Extract the other two angles, y and z, from N. - // + // + // Extract the other two angles, y and z, from N. + // - T sy = Math::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]); - y = Math::atan2 (sy, N[i][i]); - z = Math::atan2 (N[j][k], N[j][j]); + T sy = Math::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]); + y = Math::atan2 (sy, N[i][i]); + z = Math::atan2 (N[j][k], N[j][j]); } else { - // - // Extract the first angle, x. - // + // + // Extract the first angle, x. + // - x = Math::atan2 (M[j][k], M[k][k]); + x = Math::atan2 (M[j][k], M[k][k]); - // - // Remove the x rotation from M, so that the remaining - // rotation, N, is only around two axes, and gimbal lock - // cannot occur. - // + // + // Remove the x rotation from M, so that the remaining + // rotation, N, is only around two axes, and gimbal lock + // cannot occur. + // - Vec3 r (0, 0, 0); - r[i] = (_parityEven? -x: x); + Vec3 r (0, 0, 0); + r[i] = (_parityEven? -x: x); - Matrix44 N; - N.rotate (r); - N = N * M; + Matrix44 N; + N.rotate (r); + N = N * M; - // - // Extract the other two angles, y and z, from N. - // + // + // Extract the other two angles, y and z, from N. + // - T cy = Math::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]); - y = Math::atan2 (-N[i][k], cy); - z = Math::atan2 (-N[j][i], N[j][j]); + T cy = Math::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]); + y = Math::atan2 (-N[i][k], cy); + z = Math::atan2 (-N[j][i], N[j][j]); } if (!_parityEven) - *this *= -1; + *this *= -1; if (!_frameStatic) { - T t = x; - x = z; - z = t; + T t = x; + x = z; + z = t; } } @@ -653,15 +655,15 @@ Matrix33 Euler::toMatrix33() const if ( _initialRepeated ) { - M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci; - M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc; - M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss; + M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci; + M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc; + M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss; } else { - M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss; - M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc; - M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci; + M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss; + M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc; + M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci; } return M; @@ -696,15 +698,15 @@ Matrix44 Euler::toMatrix44() const if ( _initialRepeated ) { - M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci; - M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc; - M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss; + M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci; + M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc; + M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss; } else { - M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss; - M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc; - M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci; + M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss; + M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc; + M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci; } return M; @@ -743,17 +745,17 @@ Quat Euler::toQuat() const if ( _initialRepeated ) { - a[i] = cj*(cs + sc); - a[j] = sj*(cc + ss) * parity, - a[k] = sj*(cs - sc); - q.r = cj*(cc - ss); + a[i] = cj*(cs + sc); + a[j] = sj*(cc + ss) * parity, + a[k] = sj*(cs - sc); + q.r = cj*(cc - ss); } else { - a[i] = cj*sc - sj*cs, - a[j] = (cj*ss + sj*cc) * parity, - a[k] = cj*cs - sj*sc; - q.r = cj*cc + sj*ss; + a[i] = cj*sc - sj*cs, + a[j] = (cj*ss + sj*cc) * parity, + a[k] = cj*cs - sj*sc; + q.r = cj*cc + sj*ss; } q.v = a; @@ -785,16 +787,16 @@ template inline void Euler::setOrder(typename Euler::Order p) { set( p & 0x2000 ? Z : (p & 0x1000 ? Y : X), // initial axis - !(p & 0x1), // static? - !!(p & 0x100), // permutation even? - !!(p & 0x10)); // initial repeats? + !(p & 0x1), // static? + !!(p & 0x100), // permutation even? + !!(p & 0x10)); // initial repeats? } template void Euler::set(typename Euler::Axis axis, - bool relative, - bool parityEven, - bool firstRepeats) + bool relative, + bool parityEven, + bool firstRepeats) { _initialAxis = axis; _frameStatic = !relative; @@ -836,20 +838,21 @@ std::ostream& operator << (std::ostream &o, const Euler &euler) if ( euler.initialRepeated() ) k = i; return o << "(" - << euler.x << " " - << euler.y << " " - << euler.z << " " - << a[i] << a[j] << a[k] << r << ")"; + << euler.x << " " + << euler.y << " " + << euler.z << " " + << a[i] << a[j] << a[k] << r << ")"; } template float Euler::angleMod (T angle) { - angle = fmod(T (angle), T (2 * M_PI)); + const T pi = static_cast(M_PI); + angle = fmod(T (angle), T (2 * pi)); - if (angle < -M_PI) angle += 2 * M_PI; - if (angle > +M_PI) angle -= 2 * M_PI; + if (angle < -pi) angle += 2 * pi; + if (angle > +pi) angle -= 2 * pi; return angle; } @@ -867,7 +870,7 @@ Euler::simpleXYZRotation (Vec3 &xyzRot, const Vec3 &targetXyzRot) template void Euler::nearestRotation (Vec3 &xyzRot, const Vec3 &targetXyzRot, - Order order) + Order order) { int i,j,k; Euler e (0,0,0, order); @@ -881,7 +884,7 @@ Euler::nearestRotation (Vec3 &xyzRot, const Vec3 &targetXyzRot, otherXyzRot[k] = M_PI+xyzRot[k]; simpleXYZRotation(otherXyzRot, targetXyzRot); - + Vec3 d = xyzRot - targetXyzRot; Vec3 od = otherXyzRot - targetXyzRot; T dMag = d.dot(d); @@ -889,7 +892,7 @@ Euler::nearestRotation (Vec3 &xyzRot, const Vec3 &targetXyzRot, if (odMag < dMag) { - xyzRot = otherXyzRot; + xyzRot = otherXyzRot; } } @@ -918,7 +921,7 @@ Euler::makeNear (const Euler &target) #pragma warning(default:4244) #endif -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHEULER_H diff --git a/3rdparty/openexr/Imath/ImathExc.h b/3rdparty/openexr/Imath/ImathExc.h index 02ec627142..65af3b558b 100644 --- a/3rdparty/openexr/Imath/ImathExc.h +++ b/3rdparty/openexr/Imath/ImathExc.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,7 +33,6 @@ /////////////////////////////////////////////////////////////////////////// - #ifndef INCLUDED_IMATHEXC_H #define INCLUDED_IMATHEXC_H @@ -44,30 +43,31 @@ // //----------------------------------------------- +#include "ImathNamespace.h" #include "IexBaseExc.h" +#include "ImathExport.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER +// Attempt to normalize null vector +DEFINE_EXC_EXP (IMATH_EXPORT, NullVecExc, ::IEX_NAMESPACE::MathExc) -DEFINE_EXC (NullVecExc, ::Iex::MathExc) // Attempt to normalize - // null vector +// Attempt to normalize a point at infinity +DEFINE_EXC_EXP (IMATH_EXPORT, InfPointExc, ::IEX_NAMESPACE::MathExc) -DEFINE_EXC (InfPointExc, ::Iex::MathExc) // Attempt to normalize - // a point at infinity +// Attempt to normalize null quaternion +DEFINE_EXC_EXP (IMATH_EXPORT, NullQuatExc, ::IEX_NAMESPACE::MathExc) -DEFINE_EXC (NullQuatExc, ::Iex::MathExc) // Attempt to normalize - // null quaternion +// Attempt to invert singular matrix +DEFINE_EXC_EXP (IMATH_EXPORT, SingMatrixExc, ::IEX_NAMESPACE::MathExc) -DEFINE_EXC (SingMatrixExc, ::Iex::MathExc) // Attempt to invert - // singular matrix +// Attempt to remove zero scaling from matrix +DEFINE_EXC_EXP (IMATH_EXPORT, ZeroScaleExc, ::IEX_NAMESPACE::MathExc) -DEFINE_EXC (ZeroScaleExc, ::Iex::MathExc) // Attempt to remove zero - // scaling from matrix +// Attempt to normalize a vector of whose elementsare an integer type +DEFINE_EXC_EXP (IMATH_EXPORT, IntVecNormalizeExc, ::IEX_NAMESPACE::MathExc) -DEFINE_EXC (IntVecNormalizeExc, ::Iex::MathExc) // Attempt to normalize - // a vector of whose elements - // are an integer type -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHEXC_H diff --git a/3rdparty/openexr/Imath/ImathExport.h b/3rdparty/openexr/Imath/ImathExport.h new file mode 100644 index 0000000000..4357c126f8 --- /dev/null +++ b/3rdparty/openexr/Imath/ImathExport.h @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#if defined(OPENEXR_DLL) + #if defined(IMATH_EXPORTS) + #define IMATH_EXPORT __declspec(dllexport) + #define IMATH_EXPORT_CONST extern __declspec(dllexport) + #else + #define IMATH_EXPORT __declspec(dllimport) + #define IMATH_EXPORT_CONST extern __declspec(dllimport) + #endif +#else + #define IMATH_EXPORT + #define IMATH_EXPORT_CONST extern const +#endif diff --git a/3rdparty/openexr/Imath/ImathForward.h b/3rdparty/openexr/Imath/ImathForward.h new file mode 100644 index 0000000000..39d398c8c7 --- /dev/null +++ b/3rdparty/openexr/Imath/ImathForward.h @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMATHFORWARD_H +#define INCLUDED_IMATHFORWARD_H + +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER + +// +// Basic template type declarations. +// + +template class Box; +template class Color3; +template class Color4; +template class Euler; +template class Frustum; +template class FrustumTest; +template class Interval; +template class Line3; +template class Matrix33; +template class Matrix44; +template class Plane3; +template class Quat; +template class Shear6; +template class Sphere3; +template class TMatrix; +template class TMatrixBase; +template class TMatrixData; +template class Vec2; +template class Vec3; +template class Vec4; + +class Rand32; +class Rand48; + +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHFORWARD_H diff --git a/3rdparty/openexr/Imath/ImathFrame.h b/3rdparty/openexr/Imath/ImathFrame.h index c7645fc2cf..95ebb66013 100644 --- a/3rdparty/openexr/Imath/ImathFrame.h +++ b/3rdparty/openexr/Imath/ImathFrame.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -37,31 +37,33 @@ #ifndef INCLUDED_IMATHFRAME_H #define INCLUDED_IMATHFRAME_H -namespace Imath { +#include "ImathNamespace.h" + +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template class Vec3; template class Matrix44; // // These methods compute a set of reference frames, defined by their -// transformation matrix, along a curve. It is designed so that the -// array of points and the array of matrices used to fetch these routines +// transformation matrix, along a curve. It is designed so that the +// array of points and the array of matrices used to fetch these routines // don't need to be ordered as the curve. -// +// // A typical usage would be : // -// m[0] = Imath::firstFrame( p[0], p[1], p[2] ); +// m[0] = IMATH_INTERNAL_NAMESPACE::firstFrame( p[0], p[1], p[2] ); // for( int i = 1; i < n - 1; i++ ) // { -// m[i] = Imath::nextFrame( m[i-1], p[i-1], p[i], t[i-1], t[i] ); +// m[i] = IMATH_INTERNAL_NAMESPACE::nextFrame( m[i-1], p[i-1], p[i], t[i-1], t[i] ); // } -// m[n-1] = Imath::lastFrame( m[n-2], p[n-2], p[n-1] ); +// m[n-1] = IMATH_INTERNAL_NAMESPACE::lastFrame( m[n-2], p[n-2], p[n-1] ); // // See Graphics Gems I for the underlying algorithm. -// +// template Matrix44 firstFrame( const Vec3&, // First point - const Vec3&, // Second point + const Vec3&, // Second point const Vec3& ); // Third point template Matrix44 nextFrame( const Matrix44&, // Previous matrix @@ -86,7 +88,7 @@ template Matrix44 lastFrame( const Matrix44&, // Previous matrix // template Matrix44 firstFrame -( +( const Vec3& pi, // First point const Vec3& pj, // Second point const Vec3& pk ) // Third point @@ -118,13 +120,13 @@ template Matrix44 firstFrame // // nextFrame - Compute the next reference frame along a curve. // -// This function returns the transformation matrix to the next reference +// This function returns the transformation matrix to the next reference // frame defined by the previously computed transformation matrix and the // new point and tangent vector along the curve. // template Matrix44 nextFrame -( +( const Matrix44& Mi, // Previous matrix const Vec3& pi, // Previous point const Vec3& pj, // Current point @@ -137,13 +139,13 @@ template Matrix44 nextFrame if( ti.length() != 0.0 && tj.length() != 0.0 ) { ti.normalize(); tj.normalize(); - T dot = ti.dot( tj ); + T dot = ti.dot( tj ); // // This is *really* necessary : // - if( dot > 1.0 ) dot = 1.0; + if( dot > 1.0 ) dot = 1.0; else if( dot < -1.0 ) dot = -1.0; r = acosf( dot ); @@ -169,13 +171,13 @@ template Matrix44 nextFrame // // lastFrame - Compute the last reference frame along a curve. // -// This function returns the transformation matrix to the last reference +// This function returns the transformation matrix to the last reference // frame defined by the previously computed transformation matrix and the // last point along the curve. // template Matrix44 lastFrame -( +( const Matrix44& Mi, // Previous matrix const Vec3& pi, // Previous point const Vec3& pj ) // Last point @@ -185,6 +187,6 @@ template Matrix44 lastFrame return Mi * Tr; } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHFRAME_H diff --git a/3rdparty/openexr/Imath/ImathFrustum.h b/3rdparty/openexr/Imath/ImathFrustum.h index d3e5dd4c3e..4df92c90f4 100644 --- a/3rdparty/openexr/Imath/ImathFrustum.h +++ b/3rdparty/openexr/Imath/ImathFrustum.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,24 +44,26 @@ #include "ImathMatrix.h" #include "ImathLimits.h" #include "ImathFun.h" +#include "ImathNamespace.h" + #include "IexMathExc.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER // -// template class Frustum +// template class Frustum // -// The frustum is always located with the eye point at the -// origin facing down -Z. This makes the Frustum class -// compatable with OpenGL (or anything that assumes a camera -// looks down -Z, hence with a right-handed coordinate system) -// but not with RenderMan which assumes the camera looks down -// +Z. Additional functions are provided for conversion from -// and from various camera coordinate spaces. +// The frustum is always located with the eye point at the +// origin facing down -Z. This makes the Frustum class +// compatable with OpenGL (or anything that assumes a camera +// looks down -Z, hence with a right-handed coordinate system) +// but not with RenderMan which assumes the camera looks down +// +Z. Additional functions are provided for conversion from +// and from various camera coordinate spaces. // -// nearPlane/farPlane: near/far are keywords used by Microsoft's -// compiler, so we use nearPlane/farPlane instead to avoid -// issues. +// nearPlane/farPlane: near/far are keywords used by Microsoft's +// compiler, so we use nearPlane/farPlane instead to avoid +// issues. template @@ -78,46 +80,46 @@ class Frustum // Assignment operator //-------------------- - const Frustum &operator = (const Frustum &); + const Frustum & operator = (const Frustum &); //-------------------- // Operators: ==, != //-------------------- - - bool operator == (const Frustum &src) const; - bool operator != (const Frustum &src) const; + + bool operator == (const Frustum &src) const; + bool operator != (const Frustum &src) const; //-------------------------------------------------------- // Set functions change the entire state of the Frustum //-------------------------------------------------------- - void set(T nearPlane, T farPlane, - T left, T right, - T top, T bottom, - bool ortho=false); + void set(T nearPlane, T farPlane, + T left, T right, + T top, T bottom, + bool ortho=false); - void set(T nearPlane, T farPlane, T fovx, T fovy, T aspect); + void set(T nearPlane, T farPlane, T fovx, T fovy, T aspect); //------------------------------------------------------ // These functions modify an already valid frustum state //------------------------------------------------------ - void modifyNearAndFar(T nearPlane, T farPlane); - void setOrthographic(bool); + void modifyNearAndFar(T nearPlane, T farPlane); + void setOrthographic(bool); //-------------- // Access //-------------- - - bool orthographic() const { return _orthographic; } - T nearPlane() const { return _nearPlane; } - T hither() const { return _nearPlane; } - T farPlane() const { return _farPlane; } - T yon() const { return _farPlane; } - T left() const { return _left; } - T right() const { return _right; } - T bottom() const { return _bottom; } - T top() const { return _top; } + + bool orthographic() const { return _orthographic; } + T nearPlane() const { return _nearPlane; } + T hither() const { return _nearPlane; } + T farPlane() const { return _farPlane; } + T yon() const { return _farPlane; } + T left() const { return _left; } + T right() const { return _right; } + T bottom() const { return _bottom; } + T top() const { return _top; } //----------------------------------------------------------------------- // Sets the planes in p to be the six bounding planes of the frustum, in @@ -127,56 +129,56 @@ class Frustum // to transform the frustum before setting the planes. //----------------------------------------------------------------------- - void planes(Plane3 p[6]); - void planes(Plane3 p[6], const Matrix44 &M); + void planes(Plane3 p[6]) const; + void planes(Plane3 p[6], const Matrix44 &M) const; //---------------------- // Derived Quantities //---------------------- - T fovx() const; - T fovy() const; - T aspect() const; - Matrix44 projectionMatrix() const; - bool degenerate() const; + T fovx() const; + T fovy() const; + T aspect() const; + Matrix44 projectionMatrix() const; + bool degenerate() const; //----------------------------------------------------------------------- - // Takes a rectangle in the screen space (i.e., -1 <= left <= right <= 1 + // Takes a rectangle in the screen space (i.e., -1 <= left <= right <= 1 // and -1 <= bottom <= top <= 1) of this Frustum, and returns a new // Frustum whose near clipping-plane window is that rectangle in local - // space. + // space. //----------------------------------------------------------------------- - Frustum window(T left, T right, T top, T bottom) const; + Frustum window(T left, T right, T top, T bottom) const; //---------------------------------------------------------- // Projection is in screen space / Conversion from Z-Buffer //---------------------------------------------------------- - Line3 projectScreenToRay( const Vec2 & ) const; - Vec2 projectPointToScreen( const Vec3 & ) const; + Line3 projectScreenToRay( const Vec2 & ) const; + Vec2 projectPointToScreen( const Vec3 & ) const; - T ZToDepth(long zval, long min, long max) const; - T normalizedZToDepth(T zval) const; - long DepthToZ(T depth, long zmin, long zmax) const; + T ZToDepth(long zval, long min, long max) const; + T normalizedZToDepth(T zval) const; + long DepthToZ(T depth, long zmin, long zmax) const; - T worldRadius(const Vec3 &p, T radius) const; - T screenRadius(const Vec3 &p, T radius) const; + T worldRadius(const Vec3 &p, T radius) const; + T screenRadius(const Vec3 &p, T radius) const; protected: - Vec2 screenToLocal( const Vec2 & ) const; - Vec2 localToScreen( const Vec2 & ) const; + Vec2 screenToLocal( const Vec2 & ) const; + Vec2 localToScreen( const Vec2 & ) const; protected: - T _nearPlane; - T _farPlane; - T _left; - T _right; - T _top; - T _bottom; - bool _orthographic; + T _nearPlane; + T _farPlane; + T _left; + T _right; + T _top; + T _bottom; + bool _orthographic; }; @@ -184,12 +186,12 @@ template inline Frustum::Frustum() { set(T (0.1), - T (1000.0), - T (-1.0), - T (1.0), - T (1.0), - T (-1.0), - false); + T (1000.0), + T (-1.0), + T (1.0), + T (1.0), + T (-1.0), + false); } template @@ -255,11 +257,11 @@ template void Frustum::set(T n, T f, T l, T r, T t, T b, bool o) { _nearPlane = n; - _farPlane = f; - _left = l; - _right = r; - _bottom = b; - _top = t; + _farPlane = f; + _left = l; + _right = r; + _bottom = b; + _top = t; _orthographic = o; } @@ -268,24 +270,24 @@ void Frustum::modifyNearAndFar(T n, T f) { if ( _orthographic ) { - _nearPlane = n; + _nearPlane = n; } else { - Line3 lowerLeft( Vec3(0,0,0), Vec3(_left,_bottom,-_nearPlane) ); - Line3 upperRight( Vec3(0,0,0), Vec3(_right,_top,-_nearPlane) ); - Plane3 nearPlane( Vec3(0,0,-1), n ); - - Vec3 ll,ur; - nearPlane.intersect(lowerLeft,ll); - nearPlane.intersect(upperRight,ur); - - _left = ll.x; - _right = ur.x; - _top = ur.y; - _bottom = ll.y; - _nearPlane = n; - _farPlane = f; + Line3 lowerLeft( Vec3(0,0,0), Vec3(_left,_bottom,-_nearPlane) ); + Line3 upperRight( Vec3(0,0,0), Vec3(_right,_top,-_nearPlane) ); + Plane3 nearPlane( Vec3(0,0,-1), n ); + + Vec3 ll,ur; + nearPlane.intersect(lowerLeft,ll); + nearPlane.intersect(upperRight,ur); + + _left = ll.x; + _right = ur.x; + _top = ur.y; + _bottom = ll.y; + _nearPlane = n; + _farPlane = f; } _farPlane = f; @@ -301,27 +303,27 @@ template void Frustum::set(T nearPlane, T farPlane, T fovx, T fovy, T aspect) { if (fovx != 0 && fovy != 0) - throw Iex::ArgExc ("fovx and fovy cannot both be non-zero."); + throw IEX_NAMESPACE::ArgExc ("fovx and fovy cannot both be non-zero."); const T two = static_cast(2); if (fovx != 0) { - _right = nearPlane * Math::tan(fovx / two); - _left = -_right; - _top = ((_right - _left) / aspect) / two; - _bottom = -_top; + _right = nearPlane * Math::tan(fovx / two); + _left = -_right; + _top = ((_right - _left) / aspect) / two; + _bottom = -_top; } else { - _top = nearPlane * Math::tan(fovy / two); - _bottom = -_top; - _right = (_top - _bottom) * aspect / two; - _left = -_right; + _top = nearPlane * Math::tan(fovy / two); + _bottom = -_top; + _right = (_top - _bottom) * aspect / two; + _left = -_right; } - _nearPlane = nearPlane; - _farPlane = farPlane; - _orthographic = false; + _nearPlane = nearPlane; + _farPlane = farPlane; + _orthographic = false; } template @@ -343,10 +345,10 @@ T Frustum::aspect() const T topMinusBottom = _top-_bottom; if (abs(topMinusBottom) < 1 && - abs(rightMinusLeft) > limits::max() * abs(topMinusBottom)) + abs(rightMinusLeft) > limits::max() * abs(topMinusBottom)) { - throw Iex::DivzeroExc ("Bad viewing frustum: " - "aspect ratio cannot be computed."); + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "aspect ratio cannot be computed."); } return rightMinusLeft / topMinusBottom; @@ -365,76 +367,76 @@ Matrix44 Frustum::projectionMatrix() const T farMinusNear = _farPlane-_nearPlane; if ((abs(rightMinusLeft) < 1 && - abs(rightPlusLeft) > limits::max() * abs(rightMinusLeft)) || - (abs(topMinusBottom) < 1 && - abs(topPlusBottom) > limits::max() * abs(topMinusBottom)) || - (abs(farMinusNear) < 1 && - abs(farPlusNear) > limits::max() * abs(farMinusNear))) - { - throw Iex::DivzeroExc ("Bad viewing frustum: " - "projection matrix cannot be computed."); - } - - if ( _orthographic ) - { - T tx = -rightPlusLeft / rightMinusLeft; - T ty = -topPlusBottom / topMinusBottom; - T tz = -farPlusNear / farMinusNear; - - if ((abs(rightMinusLeft) < 1 && - 2 > limits::max() * abs(rightMinusLeft)) || + abs(rightPlusLeft) > limits::max() * abs(rightMinusLeft)) || (abs(topMinusBottom) < 1 && - 2 > limits::max() * abs(topMinusBottom)) || + abs(topPlusBottom) > limits::max() * abs(topMinusBottom)) || (abs(farMinusNear) < 1 && - 2 > limits::max() * abs(farMinusNear))) + abs(farPlusNear) > limits::max() * abs(farMinusNear))) { - throw Iex::DivzeroExc ("Bad viewing frustum: " - "projection matrix cannot be computed."); - } - - T A = 2 / rightMinusLeft; - T B = 2 / topMinusBottom; - T C = -2 / farMinusNear; - - return Matrix44( A, 0, 0, 0, - 0, B, 0, 0, - 0, 0, C, 0, - tx, ty, tz, 1.f ); + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "projection matrix cannot be computed."); } - else - { - T A = rightPlusLeft / rightMinusLeft; - T B = topPlusBottom / topMinusBottom; - T C = -farPlusNear / farMinusNear; - T farTimesNear = -2 * _farPlane * _nearPlane; - if (abs(farMinusNear) < 1 && - abs(farTimesNear) > limits::max() * abs(farMinusNear)) + if ( _orthographic ) { - throw Iex::DivzeroExc ("Bad viewing frustum: " - "projection matrix cannot be computed."); + T tx = -rightPlusLeft / rightMinusLeft; + T ty = -topPlusBottom / topMinusBottom; + T tz = -farPlusNear / farMinusNear; + + if ((abs(rightMinusLeft) < 1 && + 2 > limits::max() * abs(rightMinusLeft)) || + (abs(topMinusBottom) < 1 && + 2 > limits::max() * abs(topMinusBottom)) || + (abs(farMinusNear) < 1 && + 2 > limits::max() * abs(farMinusNear))) + { + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "projection matrix cannot be computed."); + } + + T A = 2 / rightMinusLeft; + T B = 2 / topMinusBottom; + T C = -2 / farMinusNear; + + return Matrix44( A, 0, 0, 0, + 0, B, 0, 0, + 0, 0, C, 0, + tx, ty, tz, 1.f ); } - - T D = farTimesNear / farMinusNear; - - T twoTimesNear = 2 * _nearPlane; - - if ((abs(rightMinusLeft) < 1 && - abs(twoTimesNear) > limits::max() * abs(rightMinusLeft)) || - (abs(topMinusBottom) < 1 && - abs(twoTimesNear) > limits::max() * abs(topMinusBottom))) + else { - throw Iex::DivzeroExc ("Bad viewing frustum: " - "projection matrix cannot be computed."); - } - - T E = twoTimesNear / rightMinusLeft; - T F = twoTimesNear / topMinusBottom; - - return Matrix44( E, 0, 0, 0, - 0, F, 0, 0, - A, B, C, -1, - 0, 0, D, 0 ); + T A = rightPlusLeft / rightMinusLeft; + T B = topPlusBottom / topMinusBottom; + T C = -farPlusNear / farMinusNear; + + T farTimesNear = -2 * _farPlane * _nearPlane; + if (abs(farMinusNear) < 1 && + abs(farTimesNear) > limits::max() * abs(farMinusNear)) + { + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "projection matrix cannot be computed."); + } + + T D = farTimesNear / farMinusNear; + + T twoTimesNear = 2 * _nearPlane; + + if ((abs(rightMinusLeft) < 1 && + abs(twoTimesNear) > limits::max() * abs(rightMinusLeft)) || + (abs(topMinusBottom) < 1 && + abs(twoTimesNear) > limits::max() * abs(topMinusBottom))) + { + throw IEX_NAMESPACE::DivzeroExc ("Bad viewing frustum: " + "projection matrix cannot be computed."); + } + + T E = twoTimesNear / rightMinusLeft; + T F = twoTimesNear / topMinusBottom; + + return Matrix44( E, 0, 0, 0, + 0, F, 0, 0, + A, B, C, -1, + 0, 0, D, 0 ); } } @@ -462,7 +464,7 @@ template Vec2 Frustum::screenToLocal(const Vec2 &s) const { return Vec2( _left + (_right-_left) * (1.f+s.x) / 2.f, - _bottom + (_top-_bottom) * (1.f+s.y) / 2.f ); + _bottom + (_top-_bottom) * (1.f+s.y) / 2.f ); } template @@ -474,17 +476,17 @@ Vec2 Frustum::localToScreen(const Vec2 &p) const T bottomMinusTop = _bottom-_top; if ((abs(leftMinusRight) < T (1) && - abs(leftPlusRight) > limits::max() * abs(leftMinusRight)) || - (abs(bottomMinusTop) < T (1) && - abs(bottomPlusTop) > limits::max() * abs(bottomMinusTop))) + abs(leftPlusRight) > limits::max() * abs(leftMinusRight)) || + (abs(bottomMinusTop) < T (1) && + abs(bottomPlusTop) > limits::max() * abs(bottomMinusTop))) { - throw Iex::DivzeroExc - ("Bad viewing frustum: " - "local-to-screen transformation cannot be computed"); + throw IEX_NAMESPACE::DivzeroExc + ("Bad viewing frustum: " + "local-to-screen transformation cannot be computed"); } return Vec2( leftPlusRight / leftMinusRight, - bottomPlusTop / bottomMinusTop ); + bottomPlusTop / bottomMinusTop ); } template @@ -492,20 +494,20 @@ Line3 Frustum::projectScreenToRay(const Vec2 &p) const { Vec2 point = screenToLocal(p); if (orthographic()) - return Line3( Vec3(point.x,point.y, 0.0), - Vec3(point.x,point.y,-_nearPlane)); + return Line3( Vec3(point.x,point.y, 0.0), + Vec3(point.x,point.y,-1.0)); else - return Line3( Vec3(0, 0, 0), Vec3(point.x,point.y,-_nearPlane)); + return Line3( Vec3(0, 0, 0), Vec3(point.x,point.y,-_nearPlane)); } template Vec2 Frustum::projectPointToScreen(const Vec3 &point) const { if (orthographic() || point.z == T (0)) - return localToScreen( Vec2( point.x, point.y ) ); + return localToScreen( Vec2( point.x, point.y ) ); else - return localToScreen( Vec2( point.x * _nearPlane / -point.z, - point.y * _nearPlane / -point.z ) ); + return localToScreen( Vec2( point.x * _nearPlane / -point.z, + point.y * _nearPlane / -point.z ) ); } template @@ -515,8 +517,8 @@ T Frustum::ZToDepth(long zval,long zmin,long zmax) const if (zdiff == 0) { - throw Iex::DivzeroExc - ("Bad call to Frustum::ZToDepth: zmax == zmin"); + throw IEX_NAMESPACE::DivzeroExc + ("Bad call to Frustum::ZToDepth: zmax == zmin"); } if ( zval > zmax+1 ) zval -= zdiff; @@ -534,21 +536,21 @@ T Frustum::normalizedZToDepth(T zval) const { return -(Zp*(_farPlane-_nearPlane) + (_farPlane+_nearPlane))/2; } - else - { - T farTimesNear = 2 * _farPlane * _nearPlane; - T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane; - - if (abs(farMinusNear) < 1 && - abs(farTimesNear) > limits::max() * abs(farMinusNear)) + else { - throw Iex::DivzeroExc - ("Frustum::normalizedZToDepth cannot be computed. The " - "near and far clipping planes of the viewing frustum " - "may be too close to each other"); - } - - return farTimesNear / farMinusNear; + T farTimesNear = 2 * _farPlane * _nearPlane; + T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane; + + if (abs(farMinusNear) < 1 && + abs(farTimesNear) > limits::max() * abs(farMinusNear)) + { + throw IEX_NAMESPACE::DivzeroExc + ("Frustum::normalizedZToDepth cannot be computed. The " + "near and far clipping planes of the viewing frustum " + "may be too close to each other"); + } + + return farTimesNear / farMinusNear; } } @@ -560,43 +562,43 @@ long Frustum::DepthToZ(T depth,long zmin,long zmax) const if ( _orthographic ) { - T farPlusNear = 2*depth + _farPlane + _nearPlane; - - if (abs(farMinusNear) < 1 && - abs(farPlusNear) > limits::max() * abs(farMinusNear)) - { - throw Iex::DivzeroExc - ("Bad viewing frustum: near and far clipping planes " - "are too close to each other"); - } - - T Zp = -farPlusNear/farMinusNear; - return long(0.5*(Zp+1)*zdiff) + zmin; - } - else - { - // Perspective - - T farTimesNear = 2*_farPlane*_nearPlane; - if (abs(depth) < 1 && - abs(farTimesNear) > limits::max() * abs(depth)) - { - throw Iex::DivzeroExc - ("Bad call to DepthToZ function: value of `depth' " - "is too small"); + T farPlusNear = 2*depth + _farPlane + _nearPlane; + + if (abs(farMinusNear) < 1 && + abs(farPlusNear) > limits::max() * abs(farMinusNear)) + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad viewing frustum: near and far clipping planes " + "are too close to each other"); + } + + T Zp = -farPlusNear/farMinusNear; + return long(0.5*(Zp+1)*zdiff) + zmin; } - - T farPlusNear = farTimesNear/depth + _farPlane + _nearPlane; - if (abs(farMinusNear) < 1 && - abs(farPlusNear) > limits::max() * abs(farMinusNear)) - { - throw Iex::DivzeroExc - ("Bad viewing frustum: near and far clipping planes " - "are too close to each other"); - } - - T Zp = farPlusNear/farMinusNear; - return long(0.5*(Zp+1)*zdiff) + zmin; + else + { + // Perspective + + T farTimesNear = 2*_farPlane*_nearPlane; + if (abs(depth) < 1 && + abs(farTimesNear) > limits::max() * abs(depth)) + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad call to DepthToZ function: value of `depth' " + "is too small"); + } + + T farPlusNear = farTimesNear/depth + _farPlane + _nearPlane; + if (abs(farMinusNear) < 1 && + abs(farPlusNear) > limits::max() * abs(farMinusNear)) + { + throw IEX_NAMESPACE::DivzeroExc + ("Bad viewing frustum: near and far clipping planes " + "are too close to each other"); + } + + T Zp = farPlusNear/farMinusNear; + return long(0.5*(Zp+1)*zdiff) + zmin; } } @@ -615,13 +617,13 @@ T Frustum::screenRadius(const Vec3 &p, T radius) const if (abs(p.z) > 1 || abs(-_nearPlane) < limits::max() * abs(p.z)) { - return radius * (-_nearPlane / p.z); + return radius * (-_nearPlane / p.z); } else { - throw Iex::DivzeroExc - ("Bad call to Frustum::screenRadius: the magnitude of `p' " - "is too small"); + throw IEX_NAMESPACE::DivzeroExc + ("Bad call to Frustum::screenRadius: the magnitude of `p' " + "is too small"); } return radius * (-_nearPlane / p.z); @@ -632,21 +634,21 @@ T Frustum::worldRadius(const Vec3 &p, T radius) const { if (abs(-_nearPlane) > 1 || abs(p.z) < limits::max() * abs(-_nearPlane)) { - return radius * (p.z / -_nearPlane); + return radius * (p.z / -_nearPlane); } else { - throw Iex::DivzeroExc - ("Bad viewing frustum: the near clipping plane is too " - "close to zero"); + throw IEX_NAMESPACE::DivzeroExc + ("Bad viewing frustum: the near clipping plane is too " + "close to zero"); } } template -void Frustum::planes(Plane3 p[6]) +void Frustum::planes(Plane3 p[6]) const { // - // Plane order: Top, Right, Bottom, Left, Near, Far. + // Plane order: Top, Right, Bottom, Left, Near, Far. // Normals point outwards. // @@ -676,10 +678,10 @@ void Frustum::planes(Plane3 p[6]) template -void Frustum::planes(Plane3 p[6], const Matrix44 &M) +void Frustum::planes(Plane3 p[6], const Matrix44 &M) const { // - // Plane order: Top, Right, Bottom, Left, Near, Far. + // Plane order: Top, Right, Bottom, Left, Near, Far. // Normals point outwards. // @@ -720,11 +722,11 @@ void Frustum::planes(Plane3 p[6], const Matrix44 &M) } } -typedef Frustum Frustumf; +typedef Frustum Frustumf; typedef Frustum Frustumd; -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #if defined _WIN32 || defined _WIN64 @@ -736,4 +738,4 @@ typedef Frustum Frustumd; #endif #endif -#endif +#endif // INCLUDED_IMATHFRUSTUM_H diff --git a/3rdparty/openexr/Imath/ImathFrustumTest.h b/3rdparty/openexr/Imath/ImathFrustumTest.h index 7ac3406d6f..d9c10cc379 100644 --- a/3rdparty/openexr/Imath/ImathFrustumTest.h +++ b/3rdparty/openexr/Imath/ImathFrustumTest.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2011-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -38,10 +38,10 @@ //------------------------------------------------------------------------- // -// This file contains algorithms applied to or in conjunction with -// Frustum visibility testing (Imath::Frustum). +// This file contains algorithms applied to or in conjunction with +// Frustum visibility testing (Imath::Frustum). // -// Methods for frustum-based rejection of primitives are contained here. +// Methods for frustum-based rejection of primitives are contained here. // //------------------------------------------------------------------------- @@ -50,8 +50,9 @@ #include "ImathSphere.h" #include "ImathMatrix.h" #include "ImathVec.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER ///////////////////////////////////////////////////////////////// // FrustumTest @@ -73,7 +74,7 @@ namespace Imath { // // Given that you already have: // Imath::Frustum myFrustum -// IMath::Matrix44 myCameraWorldMatrix +// Imath::Matrix44 myCameraWorldMatrix // // First, make a frustum test object: // FrustumTest myFrustumTest(myFrustum, myCameraWorldMatrix) @@ -133,7 +134,7 @@ public: cameraMat.makeIdentity(); setFrustum(frust, cameraMat); } - FrustumTest(Frustum &frustum, const Matrix44 &cameraMat) + FrustumTest(const Frustum &frustum, const Matrix44 &cameraMat) { setFrustum(frustum, cameraMat); } @@ -142,7 +143,7 @@ public: // setFrustum() // This updates the frustum test with a new frustum and matrix. // This should usually be called just once per frame. - void setFrustum(Frustum &frustum, const Matrix44 &cameraMat); + void setFrustum(const Frustum &frustum, const Matrix44 &cameraMat); //////////////////////////////////////////////////////////////////// // isVisible() @@ -150,18 +151,18 @@ public: bool isVisible(const Sphere3 &sphere) const; bool isVisible(const Box > &box) const; bool isVisible(const Vec3 &vec) const; - + //////////////////////////////////////////////////////////////////// // completelyContains() // Check to see if shapes are entirely contained. bool completelyContains(const Sphere3 &sphere) const; bool completelyContains(const Box > &box) const; - + // These next items are kept primarily for debugging tools. // It's useful for drawing the culling environment, and also // for getting an "outside view" of the culling frustum. - Imath::Matrix44 cameraMat() const {return cameraMatrix;} - Imath::Frustum currentFrustum() const {return currFrustum;} + IMATH_INTERNAL_NAMESPACE::Matrix44 cameraMat() const {return cameraMatrix;} + IMATH_INTERNAL_NAMESPACE::Frustum currentFrustum() const {return currFrustum;} protected: // To understand why the planes are stored this way, see @@ -188,7 +189,7 @@ protected: // This should usually only be called once per frame, or however // often the camera moves. template -void FrustumTest::setFrustum(Frustum &frustum, +void FrustumTest::setFrustum(const Frustum &frustum, const Matrix44 &cameraMat) { Plane3 frustumPlanes[6]; @@ -201,7 +202,7 @@ void FrustumTest::setFrustum(Frustum &frustum, int index = i * 3; planeNormX[i] = Vec3(frustumPlanes[index + 0].normal.x, - frustumPlanes[index + 1].normal.x, + frustumPlanes[index + 1].normal.x, frustumPlanes[index + 2].normal.x); planeNormY[i] = Vec3(frustumPlanes[index + 0].normal.y, frustumPlanes[index + 1].normal.y, @@ -210,15 +211,15 @@ void FrustumTest::setFrustum(Frustum &frustum, frustumPlanes[index + 1].normal.z, frustumPlanes[index + 2].normal.z); - planeNormAbsX[i] = Vec3(Imath::abs(planeNormX[i].x), - Imath::abs(planeNormX[i].y), - Imath::abs(planeNormX[i].z)); - planeNormAbsY[i] = Vec3(Imath::abs(planeNormY[i].x), - Imath::abs(planeNormY[i].y), - Imath::abs(planeNormY[i].z)); - planeNormAbsZ[i] = Vec3(Imath::abs(planeNormZ[i].x), - Imath::abs(planeNormZ[i].y), - Imath::abs(planeNormZ[i].z)); + planeNormAbsX[i] = Vec3(IMATH_INTERNAL_NAMESPACE::abs(planeNormX[i].x), + IMATH_INTERNAL_NAMESPACE::abs(planeNormX[i].y), + IMATH_INTERNAL_NAMESPACE::abs(planeNormX[i].z)); + planeNormAbsY[i] = Vec3(IMATH_INTERNAL_NAMESPACE::abs(planeNormY[i].x), + IMATH_INTERNAL_NAMESPACE::abs(planeNormY[i].y), + IMATH_INTERNAL_NAMESPACE::abs(planeNormY[i].z)); + planeNormAbsZ[i] = Vec3(IMATH_INTERNAL_NAMESPACE::abs(planeNormZ[i].x), + IMATH_INTERNAL_NAMESPACE::abs(planeNormZ[i].y), + IMATH_INTERNAL_NAMESPACE::abs(planeNormZ[i].z)); planeOffsetVec[i] = Vec3(frustumPlanes[index + 0].distance, frustumPlanes[index + 1].distance, @@ -242,18 +243,18 @@ bool FrustumTest::isVisible(const Sphere3 &sphere) const Vec3 radiusVec = Vec3(sphere.radius, sphere.radius, sphere.radius); // This is a vertical dot-product on three vectors at once. - Vec3 d0 = planeNormX[0] * center.x - + planeNormY[0] * center.y - + planeNormZ[0] * center.z + Vec3 d0 = planeNormX[0] * center.x + + planeNormY[0] * center.y + + planeNormZ[0] * center.z - radiusVec - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; - Vec3 d1 = planeNormX[1] * center.x - + planeNormY[1] * center.y - + planeNormZ[1] * center.z + Vec3 d1 = planeNormX[1] * center.x + + planeNormY[1] * center.y + + planeNormZ[1] * center.z - radiusVec - planeOffsetVec[1]; @@ -276,18 +277,18 @@ bool FrustumTest::completelyContains(const Sphere3 &sphere) const Vec3 radiusVec = Vec3(sphere.radius, sphere.radius, sphere.radius); // This is a vertical dot-product on three vectors at once. - Vec3 d0 = planeNormX[0] * center.x - + planeNormY[0] * center.y - + planeNormZ[0] * center.z + Vec3 d0 = planeNormX[0] * center.x + + planeNormY[0] * center.y + + planeNormZ[0] * center.z + radiusVec - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; - Vec3 d1 = planeNormX[1] * center.x - + planeNormY[1] * center.y - + planeNormZ[1] * center.z + Vec3 d1 = planeNormX[1] * center.x + + planeNormY[1] * center.y + + planeNormZ[1] * center.z + radiusVec - planeOffsetVec[1]; @@ -306,27 +307,30 @@ bool FrustumTest::completelyContains(const Sphere3 &sphere) const template bool FrustumTest::isVisible(const Box > &box) const { + if (box.isEmpty()) + return false; + Vec3 center = (box.min + box.max) / 2; Vec3 extent = (box.max - center); // This is a vertical dot-product on three vectors at once. - Vec3 d0 = planeNormX[0] * center.x - + planeNormY[0] * center.y + Vec3 d0 = planeNormX[0] * center.x + + planeNormY[0] * center.y + planeNormZ[0] * center.z - - planeNormAbsX[0] * extent.x - - planeNormAbsY[0] * extent.y - - planeNormAbsZ[0] * extent.z + - planeNormAbsX[0] * extent.x + - planeNormAbsY[0] * extent.y + - planeNormAbsZ[0] * extent.z - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; - Vec3 d1 = planeNormX[1] * center.x - + planeNormY[1] * center.y + Vec3 d1 = planeNormX[1] * center.x + + planeNormY[1] * center.y + planeNormZ[1] * center.z - - planeNormAbsX[1] * extent.x - - planeNormAbsY[1] * extent.y - - planeNormAbsZ[1] * extent.z + - planeNormAbsX[1] * extent.x + - planeNormAbsY[1] * extent.y + - planeNormAbsZ[1] * extent.z - planeOffsetVec[1]; if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) @@ -344,27 +348,30 @@ bool FrustumTest::isVisible(const Box > &box) const template bool FrustumTest::completelyContains(const Box > &box) const { + if (box.isEmpty()) + return false; + Vec3 center = (box.min + box.max) / 2; Vec3 extent = (box.max - center); // This is a vertical dot-product on three vectors at once. - Vec3 d0 = planeNormX[0] * center.x - + planeNormY[0] * center.y + Vec3 d0 = planeNormX[0] * center.x + + planeNormY[0] * center.y + planeNormZ[0] * center.z - + planeNormAbsX[0] * extent.x - + planeNormAbsY[0] * extent.y - + planeNormAbsZ[0] * extent.z + + planeNormAbsX[0] * extent.x + + planeNormAbsY[0] * extent.y + + planeNormAbsZ[0] * extent.z - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; - Vec3 d1 = planeNormX[1] * center.x - + planeNormY[1] * center.y + Vec3 d1 = planeNormX[1] * center.x + + planeNormY[1] * center.y + planeNormZ[1] * center.z - + planeNormAbsX[1] * extent.x - + planeNormAbsY[1] * extent.y - + planeNormAbsZ[1] * extent.z + + planeNormAbsX[1] * extent.x + + planeNormAbsY[1] * extent.y + + planeNormAbsZ[1] * extent.z - planeOffsetVec[1]; if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) @@ -382,17 +389,17 @@ template bool FrustumTest::isVisible(const Vec3 &vec) const { // This is a vertical dot-product on three vectors at once. - Vec3 d0 = (planeNormX[0] * vec.x) - + (planeNormY[0] * vec.y) - + (planeNormZ[0] * vec.z) + Vec3 d0 = (planeNormX[0] * vec.x) + + (planeNormY[0] * vec.y) + + (planeNormZ[0] * vec.z) - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; - Vec3 d1 = (planeNormX[1] * vec.x) - + (planeNormY[1] * vec.y) - + (planeNormZ[1] * vec.z) + Vec3 d1 = (planeNormX[1] * vec.x) + + (planeNormY[1] * vec.y) + + (planeNormZ[1] * vec.z) - planeOffsetVec[1]; if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) @@ -405,6 +412,6 @@ bool FrustumTest::isVisible(const Vec3 &vec) const typedef FrustumTest FrustumTestf; typedef FrustumTest FrustumTestd; -} //namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHFRUSTUMTEST_H diff --git a/3rdparty/openexr/Imath/ImathFun.cpp b/3rdparty/openexr/Imath/ImathFun.cpp index e4ddf3753b..65cf62024b 100644 --- a/3rdparty/openexr/Imath/ImathFun.cpp +++ b/3rdparty/openexr/Imath/ImathFun.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -35,7 +35,7 @@ #include "ImathFun.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER float @@ -124,7 +124,7 @@ succd (double d) u.i = 0x0000000000000001LL; } - else if (u.i > 0) + else if (u.d > 0) { // Positive double, normalized or denormalized. // Incrementing the largest positive double @@ -159,7 +159,7 @@ predd (double d) u.i = 0x8000000000000001LL; } - else if (u.i > 0) + else if (u.d > 0) { // Positive double, normalized or denormalized. @@ -178,4 +178,4 @@ predd (double d) } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/Imath/ImathFun.h b/3rdparty/openexr/Imath/ImathFun.h index 863db75f1e..068c68251b 100644 --- a/3rdparty/openexr/Imath/ImathFun.h +++ b/3rdparty/openexr/Imath/ImathFun.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,10 +43,12 @@ // //----------------------------------------------------------------------------- +#include "ImathExport.h" #include "ImathLimits.h" #include "ImathInt64.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template inline T @@ -98,7 +100,7 @@ lerpfactor(T m, T a, T b) T n = m - a; if (abs(d) > T(1) || abs(n) < limits::max() * abs(d)) - return n / d; + return n / d; return T(0); } @@ -116,7 +118,7 @@ template inline int cmp (T a, T b) { - return Imath::sign (a - b); + return IMATH_INTERNAL_NAMESPACE::sign (a - b); } @@ -124,7 +126,7 @@ template inline int cmpt (T a, T b, T t) { - return (Imath::abs (a - b) <= t)? 0 : cmp (a, b); + return (IMATH_INTERNAL_NAMESPACE::abs (a - b) <= t)? 0 : cmp (a, b); } @@ -132,7 +134,7 @@ template inline bool iszero (T a, T t) { - return (Imath::abs (a) <= t) ? 1 : 0; + return (IMATH_INTERNAL_NAMESPACE::abs (a) <= t) ? 1 : 0; } @@ -140,7 +142,7 @@ template inline bool equal (T1 a, T2 b, T3 t) { - return Imath::abs (a - b) <= t; + return IMATH_INTERNAL_NAMESPACE::abs (a - b) <= t; } template @@ -178,7 +180,7 @@ inline int divs (int x, int y) { return (x >= 0)? ((y >= 0)? ( x / y): -( x / -y)): - ((y >= 0)? -(-x / y): (-x / -y)); + ((y >= 0)? -(-x / y): (-x / -y)); } @@ -186,7 +188,7 @@ inline int mods (int x, int y) { return (x >= 0)? ((y >= 0)? ( x % y): ( x % -y)): - ((y >= 0)? -(-x % y): -(-x % -y)); + ((y >= 0)? -(-x % y): -(-x % -y)); } @@ -196,13 +198,13 @@ mods (int x, int y) // // divp(x,y) == floor (double(x) / double (y)) // modp(x,y) == x - y * divp(x,y) -// +// inline int divp (int x, int y) { return (x >= 0)? ((y >= 0)? ( x / y): -( x / -y)): - ((y >= 0)? -((y-1-x) / y): ((-y-1-x) / -y)); + ((y >= 0)? -((y-1-x) / y): ((-y-1-x) / -y)); } @@ -220,7 +222,7 @@ modp (int x, int y) // // predf(f) returns float(f-e), where e is the smallest // positive number such that float(f-e) != f. -// +// // succd(d) returns double(d+e), where e is the smallest // positive number such that double(d+e) != d. // @@ -230,20 +232,20 @@ modp (int x, int y) // Exceptions: If the input value is an infinity or a nan, // succf(), predf(), succd(), and predd() all // return the input value without changing it. -// +// //---------------------------------------------------------- -float succf (float f); -float predf (float f); +IMATH_EXPORT float succf (float f); +IMATH_EXPORT float predf (float f); -double succd (double d); -double predd (double d); +IMATH_EXPORT double succd (double d); +IMATH_EXPORT double predd (double d); // // Return true if the number is not a NaN or Infinity. // -inline bool +inline bool finitef (float f) { union {float f; int i;} u; @@ -252,7 +254,7 @@ finitef (float f) return (u.i & 0x7f800000) != 0x7f800000; } -inline bool +inline bool finited (double d) { union {double d; Int64 i;} u; @@ -262,6 +264,6 @@ finited (double d) } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHFUN_H diff --git a/3rdparty/openexr/Imath/ImathGL.h b/3rdparty/openexr/Imath/ImathGL.h deleted file mode 100644 index 6217f50a3e..0000000000 --- a/3rdparty/openexr/Imath/ImathGL.h +++ /dev/null @@ -1,159 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas -// Digital Ltd. LLC -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Industrial Light & Magic nor the names of -// its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////// - - -#ifndef INCLUDED_IMATHGL_H -#define INCLUDED_IMATHGL_H - -#include - -#include "ImathVec.h" -#include "ImathMatrix.h" -#include "IexMathExc.h" -#include "ImathFun.h" - -inline void glVertex ( const Imath::V3f &v ) { glVertex3f(v.x,v.y,v.z); } -inline void glVertex ( const Imath::V2f &v ) { glVertex2f(v.x,v.y); } -inline void glNormal ( const Imath::V3f &n ) { glNormal3f(n.x,n.y,n.z); } -inline void glColor ( const Imath::V3f &c ) { glColor3f(c.x,c.y,c.z); } -inline void glTranslate ( const Imath::V3f &t ) { glTranslatef(t.x,t.y,t.z); } - -inline void glTexCoord( const Imath::V2f &t ) -{ - glTexCoord2f(t.x,t.y); -} - -inline void glDisableTexture() -{ - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - - glActiveTexture(GL_TEXTURE0); -} - -namespace { - -const float GL_FLOAT_MAX = 1.8e+19; // sqrt (FLT_MAX) - -inline bool -badFloat (float f) -{ - return !Imath::finitef (f) || f < - GL_FLOAT_MAX || f > GL_FLOAT_MAX; -} - -} // namespace - -inline void -throwBadMatrix (const Imath::M44f& m) -{ - if (badFloat (m[0][0]) || - badFloat (m[0][1]) || - badFloat (m[0][2]) || - badFloat (m[0][3]) || - badFloat (m[1][0]) || - badFloat (m[1][1]) || - badFloat (m[1][2]) || - badFloat (m[1][3]) || - badFloat (m[2][0]) || - badFloat (m[2][1]) || - badFloat (m[2][2]) || - badFloat (m[2][3]) || - badFloat (m[3][0]) || - badFloat (m[3][1]) || - badFloat (m[3][2]) || - badFloat (m[3][3])) - throw Iex::OverflowExc ("GL matrix overflow"); -} - -inline void -glMultMatrix( const Imath::M44f& m ) -{ - throwBadMatrix (m); - glMultMatrixf( (GLfloat*)m[0] ); -} - -inline void -glMultMatrix( const Imath::M44f* m ) -{ - throwBadMatrix (*m); - glMultMatrixf( (GLfloat*)(*m)[0] ); -} - -inline void -glLoadMatrix( const Imath::M44f& m ) -{ - throwBadMatrix (m); - glLoadMatrixf( (GLfloat*)m[0] ); -} - -inline void -glLoadMatrix( const Imath::M44f* m ) -{ - throwBadMatrix (*m); - glLoadMatrixf( (GLfloat*)(*m)[0] ); -} - - -namespace Imath { - -// -// Class objects that push/pop the GL state. These objects assist with -// proper cleanup of the state when exceptions are thrown. -// - -class GLPushMatrix { - public: - - GLPushMatrix () { glPushMatrix(); } - ~GLPushMatrix() { glPopMatrix(); } -}; - -class GLPushAttrib { - public: - - GLPushAttrib (GLbitfield mask) { glPushAttrib (mask); } - ~GLPushAttrib() { glPopAttrib(); } -}; - -class GLBegin { - public: - - GLBegin (GLenum mode) { glBegin (mode); } - ~GLBegin() { glEnd(); } -}; - -} // namespace Imath - -#endif diff --git a/3rdparty/openexr/Imath/ImathHalfLimits.h b/3rdparty/openexr/Imath/ImathHalfLimits.h index a45c6f8547..de54bd6ce3 100644 --- a/3rdparty/openexr/Imath/ImathHalfLimits.h +++ b/3rdparty/openexr/Imath/ImathHalfLimits.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,9 +44,11 @@ //-------------------------------------------------- #include "ImathLimits.h" +#include "ImathNamespace.h" + #include "half.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template <> @@ -61,6 +63,6 @@ struct limits }; -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHHALFLIMITS_H diff --git a/3rdparty/openexr/Imath/ImathInt64.h b/3rdparty/openexr/Imath/ImathInt64.h index 0719f830e2..00102d6857 100644 --- a/3rdparty/openexr/Imath/ImathInt64.h +++ b/3rdparty/openexr/Imath/ImathInt64.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2006-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -42,20 +42,24 @@ // //---------------------------------------------------------------------------- +#include "ImathNamespace.h" #include -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER #if (defined _WIN32 || defined _WIN64) && _MSC_VER >= 1300 typedef unsigned __int64 Int64; + typedef __int64 SInt64; #elif ULONG_MAX == 18446744073709551615LU typedef long unsigned int Int64; + typedef long int SInt64; #else typedef long long unsigned int Int64; + typedef long long int SInt64; #endif -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATH_INT64_H diff --git a/3rdparty/openexr/Imath/ImathInterval.h b/3rdparty/openexr/Imath/ImathInterval.h index 84ef124da9..0062f4d0a2 100644 --- a/3rdparty/openexr/Imath/ImathInterval.h +++ b/3rdparty/openexr/Imath/ImathInterval.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -50,11 +50,12 @@ //------------------------------------------------------------------- #include "ImathVec.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER -template +template class Interval { public: @@ -70,14 +71,14 @@ class Interval // Constructors - an "empty" Interval is created by default //----------------------------------------------------- - Interval(); + Interval(); Interval(const T& point); Interval(const T& minT, const T& maxT); //-------------------------------- // Operators: we get != from STL //-------------------------------- - + bool operator == (const Interval &src) const; //------------------ @@ -161,10 +162,10 @@ inline void Interval::extendBy(const T& point) { if ( point < min ) - min = point; - + min = point; + if ( point > max ) - max = point; + max = point; } template @@ -172,10 +173,10 @@ inline void Interval::extendBy(const Interval& interval) { if ( interval.min < min ) - min = interval.min; + min = interval.min; if ( interval.max > max ) - max = interval.max; + max = interval.max; } template @@ -192,17 +193,17 @@ Interval::intersects(const Interval& interval) const return interval.max >= min && interval.min <= max; } -template +template inline T -Interval::size() const -{ +Interval::size() const +{ return max-min; } -template +template inline T -Interval::center() const -{ +Interval::center() const +{ return (max+min)/2; } @@ -219,6 +220,7 @@ inline bool Interval::hasVolume() const return max > min; } -} // namespace Imath -#endif +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT + +#endif // INCLUDED_IMATHINTERVAL_H diff --git a/3rdparty/openexr/Imath/ImathLimits.h b/3rdparty/openexr/Imath/ImathLimits.h index 544578a1af..eb6f9998e5 100644 --- a/3rdparty/openexr/Imath/ImathLimits.h +++ b/3rdparty/openexr/Imath/ImathLimits.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,6 +43,7 @@ // //---------------------------------------------------------------- +#include "ImathNamespace.h" #include #include @@ -59,7 +60,7 @@ #endif #endif -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER //----------------------------------------------------------------- @@ -262,6 +263,6 @@ struct limits }; -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHLIMITS_H diff --git a/3rdparty/openexr/Imath/ImathLine.h b/3rdparty/openexr/Imath/ImathLine.h index 92d941d8af..61e4508b9f 100644 --- a/3rdparty/openexr/Imath/ImathLine.h +++ b/3rdparty/openexr/Imath/ImathLine.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,8 +46,9 @@ #include "ImathVec.h" #include "ImathLimits.h" #include "ImathMatrix.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template @@ -57,7 +58,7 @@ class Line3 Vec3 pos; Vec3 dir; - + //------------------------------------------------------------- // Constructors - default is normalized units along direction //------------------------------------------------------------- @@ -69,8 +70,8 @@ class Line3 // State Query/Set //------------------ - void set(const Vec3& point1, - const Vec3& point2); + void set(const Vec3& point1, + const Vec3& point2); //------- // F(t) @@ -140,7 +141,7 @@ inline T Line3::distanceTo(const Line3& line) const } template -inline Vec3 +inline Vec3 Line3::closestPointTo(const Line3& line) const { // Assumes the lines are normalized @@ -157,10 +158,10 @@ Line3::closestPointTo(const Line3& line) const if (absDenom < 1) { - T absNum = ((num >= 0)? num: -num); + T absNum = ((num >= 0)? num: -num); - if (absNum >= absDenom * limits::max()) - return pos; + if (absNum >= absDenom * limits::max()) + return pos; } return pos + dir * (num / denom); @@ -179,6 +180,6 @@ inline Line3 operator * (const Line3 &line, const Matrix44 &M) } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHLINE_H diff --git a/3rdparty/openexr/Imath/ImathLineAlgo.h b/3rdparty/openexr/Imath/ImathLineAlgo.h index 62bd6f531b..b08a1ffee3 100644 --- a/3rdparty/openexr/Imath/ImathLineAlgo.h +++ b/3rdparty/openexr/Imath/ImathLineAlgo.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -74,8 +74,9 @@ #include "ImathLine.h" #include "ImathVecAlgo.h" #include "ImathFun.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template @@ -104,16 +105,16 @@ closestPoints T absD = abs (d); if ((absD > 1) || - (abs (n1) < limits::max() * absD && - abs (n2) < limits::max() * absD)) + (abs (n1) < limits::max() * absD && + abs (n2) < limits::max() * absD)) { - point1 = line1 (n1 / d); - point2 = line2 (n2 / d); - return true; + point1 = line1 (n1 / d); + point2 = line2 (n2 / d); + return true; } else { - return false; + return false; } } @@ -160,9 +161,9 @@ intersect T l = normal.length(); if (l != 0) - normal /= l; + normal /= l; else - return false; // zero-area triangle + return false; // zero-area triangle // // d is the distance of line.pos from the plane that contains the triangle. @@ -173,9 +174,9 @@ intersect T nd = normal ^ line.dir; if (abs (nd) > 1 || abs (d) < limits::max() * abs (nd)) - pt = line (d / nd); + pt = line (d / nd); else - return false; // line and plane are nearly parallel + return false; // line and plane are nearly parallel // // Compute the barycentric coordinates of the intersection point. @@ -184,39 +185,39 @@ intersect // { - Vec3 en = edge0.normalized(); - Vec3 a = pt - v0; - Vec3 b = v2 - v0; - Vec3 c = (a - en * (en ^ a)); - Vec3 d = (b - en * (en ^ b)); - T e = c ^ d; - T f = d ^ d; - - if (e >= 0 && e <= f) - barycentric.z = e / f; - else - return false; // outside + Vec3 en = edge0.normalized(); + Vec3 a = pt - v0; + Vec3 b = v2 - v0; + Vec3 c = (a - en * (en ^ a)); + Vec3 d = (b - en * (en ^ b)); + T e = c ^ d; + T f = d ^ d; + + if (e >= 0 && e <= f) + barycentric.z = e / f; + else + return false; // outside } { - Vec3 en = edge1.normalized(); - Vec3 a = pt - v1; - Vec3 b = v0 - v1; - Vec3 c = (a - en * (en ^ a)); - Vec3 d = (b - en * (en ^ b)); - T e = c ^ d; - T f = d ^ d; - - if (e >= 0 && e <= f) - barycentric.x = e / f; - else - return false; // outside + Vec3 en = edge1.normalized(); + Vec3 a = pt - v1; + Vec3 b = v0 - v1; + Vec3 c = (a - en * (en ^ a)); + Vec3 d = (b - en * (en ^ b)); + T e = c ^ d; + T f = d ^ d; + + if (e >= 0 && e <= f) + barycentric.x = e / f; + else + return false; // outside } barycentric.y = 1 - barycentric.x - barycentric.z; if (barycentric.y < 0) - return false; // outside + return false; // outside front = ((line.dir ^ normal) < 0); return true; @@ -233,7 +234,7 @@ closestVertex { Vec3 nearest = v0; T neardot = (v0 - l.closestPointTo(v0)).length2(); - + T tmp = (v1 - l.closestPointTo(v1)).length2(); if (tmp < neardot) @@ -276,12 +277,12 @@ rotatePoint (const Vec3 p, Line3 l, T angle) T cosangle = Math::cos(angle); T sinangle = Math::sin(angle); - Vec3 r = q + x * radius * cosangle + y * radius * sinangle; + Vec3 r = q + x * radius * cosangle + y * radius * sinangle; return r; } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHLINEALGO_H diff --git a/3rdparty/openexr/Imath/ImathMath.h b/3rdparty/openexr/Imath/ImathMath.h index ae2503dfa0..1961d5a82c 100644 --- a/3rdparty/openexr/Imath/ImathMath.h +++ b/3rdparty/openexr/Imath/ImathMath.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -82,15 +82,16 @@ #include "ImathPlatform.h" #include "ImathLimits.h" +#include "ImathNamespace.h" #include -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template struct Math { - static T acos (T x) {return ::acos (double(x));} + static T acos (T x) {return ::acos (double(x));} static T asin (T x) {return ::asin (double(x));} static T atan (T x) {return ::atan (double(x));} static T atan2 (T x, T y) {return ::atan2 (double(x), double(y));} @@ -107,8 +108,8 @@ struct Math { double ival; T rval( ::modf (double(x),&ival)); - *iptr = ival; - return rval; + *iptr = ival; + return rval; } static T pow (T x, T y) {return ::pow (double(x), double(y));} static T sqrt (T x) {return ::sqrt (double(x));} @@ -123,7 +124,7 @@ struct Math template <> struct Math { - static float acos (float x) {return ::acosf (x);} + static float acos (float x) {return ::acosf (x);} static float asin (float x) {return ::asinf (x);} static float atan (float x) {return ::atanf (x);} static float atan2 (float x, float y) {return ::atan2f (x, y);} @@ -161,9 +162,9 @@ inline T sinx_over_x (T x) { if (x * x < limits::epsilon()) - return T (1); + return T (1); else - return Math::sin (x) / x; + return Math::sin (x) / x; } @@ -174,14 +175,14 @@ sinx_over_x (T x) // // Returns true if x1 is the same as x2 with an absolute error of // no more than e, -// +// // abs (x1 - x2) <= e // // equalWithRelError (x1, x2, e) // // Returns true if x1 is the same as x2 with an relative error of // no more than e, -// +// // abs (x1 - x2) <= e * x1 // //-------------------------------------------------------------------------- @@ -202,7 +203,6 @@ equalWithRelError (T x1, T x2, T e) } +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imath - -#endif +#endif // INCLUDED_IMATHMATH_H diff --git a/3rdparty/openexr/Imath/ImathMatrix.h b/3rdparty/openexr/Imath/ImathMatrix.h index f1bf2cd1ae..5729c73458 100644 --- a/3rdparty/openexr/Imath/ImathMatrix.h +++ b/3rdparty/openexr/Imath/ImathMatrix.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -48,6 +48,7 @@ #include "ImathExc.h" #include "ImathVec.h" #include "ImathShear.h" +#include "ImathNamespace.h" #include #include @@ -60,7 +61,7 @@ #endif -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER enum Uninitialized {UNINITIALIZED}; @@ -121,7 +122,7 @@ template class Matrix33 //---------------------- // Compatibility with Sb //---------------------- - + T * getValue (); const T * getValue () const; @@ -258,20 +259,16 @@ template class Matrix33 // inverse() and invert() are significantly faster than // gjInverse() and gjInvert(), but the results may be slightly // less accurate. - // + // //------------------------------------------------------------ - const Matrix33 & invert (bool singExc = false) - throw (Iex::MathExc); + const Matrix33 & invert (bool singExc = false); - Matrix33 inverse (bool singExc = false) const - throw (Iex::MathExc); + Matrix33 inverse (bool singExc = false) const; - const Matrix33 & gjInvert (bool singExc = false) - throw (Iex::MathExc); + const Matrix33 & gjInvert (bool singExc = false); - Matrix33 gjInverse (bool singExc = false) const - throw (Iex::MathExc); + Matrix33 gjInverse (bool singExc = false) const; //------------------------------------------------ @@ -284,7 +281,7 @@ template class Matrix33 // Build a minor using the specified rows and columns //--------------------------------------------------- - T fastMinor (const int r0, const int r1, + T fastMinor (const int r0, const int r1, const int c0, const int c1) const; //------------ @@ -492,7 +489,7 @@ template class Matrix44 //---------------------- // Compatibility with Sb //---------------------- - + T * getValue (); const T * getValue () const; @@ -632,20 +629,16 @@ template class Matrix44 // inverse() and invert() are significantly faster than // gjInverse() and gjInvert(), but the results may be slightly // less accurate. - // + // //------------------------------------------------------------ - const Matrix44 & invert (bool singExc = false) - throw (Iex::MathExc); + const Matrix44 & invert (bool singExc = false); - Matrix44 inverse (bool singExc = false) const - throw (Iex::MathExc); + Matrix44 inverse (bool singExc = false) const; - const Matrix44 & gjInvert (bool singExc = false) - throw (Iex::MathExc); + const Matrix44 & gjInvert (bool singExc = false); - Matrix44 gjInverse (bool singExc = false) const - throw (Iex::MathExc); + Matrix44 gjInverse (bool singExc = false) const; //------------------------------------------------ @@ -752,7 +745,7 @@ template class Matrix44 // Set matrix to shear by given factors. The resulting matrix // will shear x for each y coord. by a factor of h.xy ; // will shear x for each z coord. by a factor of h.xz ; - // will shear y for each z coord. by a factor of h.yz ; + // will shear y for each z coord. by a factor of h.yz ; // will shear y for each x coord. by a factor of h.yx ; // will shear z for each x coord. by a factor of h.zx ; // will shear z for each y coord. by a factor of h.zy . @@ -763,7 +756,7 @@ template class Matrix44 //-------------------------------------------------------- - // Shear the matrix by given vector. The composed matrix + // Shear the matrix by given vector. The composed matrix // will be * , where the shear matrix ... // will shear x for each y coord. by a factor of h[0] ; // will shear x for each z coord. by a factor of h[1] ; @@ -782,7 +775,7 @@ template class Matrix44 //------------------------------------------------------------ - // Shear the matrix by the given factors. The composed matrix + // Shear the matrix by the given factors. The composed matrix // will be * , where the shear matrix ... // will shear x for each y coord. by a factor of h.xy ; // will shear x for each z coord. by a factor of h.xz ; @@ -829,10 +822,10 @@ template class Matrix44 //-------------- template -std::ostream & operator << (std::ostream & s, const Matrix33 &m); +std::ostream & operator << (std::ostream & s, const Matrix33 &m); template -std::ostream & operator << (std::ostream & s, const Matrix44 &m); +std::ostream & operator << (std::ostream & s, const Matrix44 &m); //--------------------------------------------- @@ -918,7 +911,7 @@ Matrix33::Matrix33 (T a) template inline -Matrix33::Matrix33 (const T a[3][3]) +Matrix33::Matrix33 (const T a[3][3]) { memcpy (x, a, sizeof (x)); } @@ -1118,7 +1111,7 @@ Matrix33::equalWithAbsError (const Matrix33 &m, T e) const { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) - if (!Imath::equalWithAbsError ((*this)[i][j], m[i][j], e)) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i][j], m[i][j], e)) return false; return true; @@ -1130,7 +1123,7 @@ Matrix33::equalWithRelError (const Matrix33 &m, T e) const { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) - if (!Imath::equalWithRelError ((*this)[i][j], m[i][j], e)) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i][j], m[i][j], e)) return false; return true; @@ -1166,7 +1159,7 @@ Matrix33::operator += (T a) x[2][0] += a; x[2][1] += a; x[2][2] += a; - + return *this; } @@ -1198,7 +1191,7 @@ Matrix33::operator -= (const Matrix33 &v) x[2][0] -= v.x[2][0]; x[2][1] -= v.x[2][1]; x[2][2] -= v.x[2][2]; - + return *this; } @@ -1215,7 +1208,7 @@ Matrix33::operator -= (T a) x[2][0] -= a; x[2][1] -= a; x[2][2] -= a; - + return *this; } @@ -1279,7 +1272,7 @@ Matrix33::operator *= (T a) x[2][0] *= a; x[2][1] *= a; x[2][2] *= a; - + return *this; } @@ -1376,7 +1369,7 @@ Matrix33::operator /= (T a) x[2][0] /= a; x[2][1] /= a; x[2][2] /= a; - + return *this; } @@ -1429,7 +1422,7 @@ Matrix33::transposed () const template const Matrix33 & -Matrix33::gjInvert (bool singExc) throw (Iex::MathExc) +Matrix33::gjInvert (bool singExc) { *this = gjInverse (singExc); return *this; @@ -1437,7 +1430,7 @@ Matrix33::gjInvert (bool singExc) throw (Iex::MathExc) template Matrix33 -Matrix33::gjInverse (bool singExc) const throw (Iex::MathExc) +Matrix33::gjInverse (bool singExc) const { int i, j, k; Matrix33 s; @@ -1471,7 +1464,7 @@ Matrix33::gjInverse (bool singExc) const throw (Iex::MathExc) if (pivotsize == 0) { if (singExc) - throw ::Imath::SingMatrixExc ("Cannot invert singular matrix."); + throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix."); return Matrix33(); } @@ -1513,7 +1506,7 @@ Matrix33::gjInverse (bool singExc) const throw (Iex::MathExc) if ((f = t[i][i]) == 0) { if (singExc) - throw ::Imath::SingMatrixExc ("Cannot invert singular matrix."); + throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix."); return Matrix33(); } @@ -1541,7 +1534,7 @@ Matrix33::gjInverse (bool singExc) const throw (Iex::MathExc) template const Matrix33 & -Matrix33::invert (bool singExc) throw (Iex::MathExc) +Matrix33::invert (bool singExc) { *this = inverse (singExc); return *this; @@ -1549,7 +1542,7 @@ Matrix33::invert (bool singExc) throw (Iex::MathExc) template Matrix33 -Matrix33::inverse (bool singExc) const throw (Iex::MathExc) +Matrix33::inverse (bool singExc) const { if (x[0][2] != 0 || x[1][2] != 0 || x[2][2] != 1) { @@ -1567,7 +1560,7 @@ Matrix33::inverse (bool singExc) const throw (Iex::MathExc) T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; - if (Imath::abs (r) >= 1) + if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { @@ -1579,13 +1572,13 @@ Matrix33::inverse (bool singExc) const throw (Iex::MathExc) } else { - T mr = Imath::abs (r) / limits::smallest(); + T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / limits::smallest(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { - if (mr > Imath::abs (s[i][j])) + if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } @@ -1606,7 +1599,7 @@ Matrix33::inverse (bool singExc) const throw (Iex::MathExc) { Matrix33 s ( x[1][1], -x[0][1], - 0, + 0, -x[1][0], x[0][0], @@ -1618,7 +1611,7 @@ Matrix33::inverse (bool singExc) const throw (Iex::MathExc) T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; - if (Imath::abs (r) >= 1) + if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { @@ -1630,13 +1623,13 @@ Matrix33::inverse (bool singExc) const throw (Iex::MathExc) } else { - T mr = Imath::abs (r) / limits::smallest(); + T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / limits::smallest(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { - if (mr > Imath::abs (s[i][j])) + if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } @@ -1783,7 +1776,7 @@ Matrix33::setTranslation (const Vec2 &t) } template -inline Vec2 +inline Vec2 Matrix33::translation () const { return Vec2 (x[2][0], x[2][1]); @@ -1847,10 +1840,10 @@ const Matrix33 & Matrix33::shear (const S &xy) { // - // In this case, we don't need a temp. copy of the matrix - // because we never use a value on the RHS after we've + // In this case, we don't need a temp. copy of the matrix + // because we never use a value on the RHS after we've // changed it on the LHS. - // + // x[1][0] += xy * x[0][0]; x[1][1] += xy * x[0][1]; @@ -1865,11 +1858,11 @@ const Matrix33 & Matrix33::shear (const Vec2 &h) { Matrix33 P (*this); - + x[0][0] = P[0][0] + h[1] * P[1][0]; x[0][1] = P[0][1] + h[1] * P[1][1]; x[0][2] = P[0][2] + h[1] * P[1][2]; - + x[1][0] = P[1][0] + h[0] * P[0][0]; x[1][1] = P[1][1] + h[0] * P[0][1]; x[1][2] = P[1][2] + h[0] * P[0][2]; @@ -1931,7 +1924,7 @@ Matrix44::Matrix44 (T a) template inline -Matrix44::Matrix44 (const T a[4][4]) +Matrix44::Matrix44 (const T a[4][4]) { memcpy (x, a, sizeof (x)); } @@ -2242,7 +2235,7 @@ Matrix44::equalWithAbsError (const Matrix44 &m, T e) const { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) - if (!Imath::equalWithAbsError ((*this)[i][j], m[i][j], e)) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i][j], m[i][j], e)) return false; return true; @@ -2254,7 +2247,7 @@ Matrix44::equalWithRelError (const Matrix44 &m, T e) const { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) - if (!Imath::equalWithRelError ((*this)[i][j], m[i][j], e)) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i][j], m[i][j], e)) return false; return true; @@ -2526,11 +2519,11 @@ Matrix44::multiply (const Matrix44 &a, const Matrix44 &b, Matrix44 &c) { - register const T * IMATH_RESTRICT ap = &a.x[0][0]; - register const T * IMATH_RESTRICT bp = &b.x[0][0]; - register T * IMATH_RESTRICT cp = &c.x[0][0]; + const T * IMATH_RESTRICT ap = &a.x[0][0]; + const T * IMATH_RESTRICT bp = &b.x[0][0]; + T * IMATH_RESTRICT cp = &c.x[0][0]; - register T a0, a1, a2, a3; + T a0, a1, a2, a3; a0 = ap[0]; a1 = ap[1]; @@ -2698,7 +2691,7 @@ Matrix44::transposed () const template const Matrix44 & -Matrix44::gjInvert (bool singExc) throw (Iex::MathExc) +Matrix44::gjInvert (bool singExc) { *this = gjInverse (singExc); return *this; @@ -2706,7 +2699,7 @@ Matrix44::gjInvert (bool singExc) throw (Iex::MathExc) template Matrix44 -Matrix44::gjInverse (bool singExc) const throw (Iex::MathExc) +Matrix44::gjInverse (bool singExc) const { int i, j, k; Matrix44 s; @@ -2740,7 +2733,7 @@ Matrix44::gjInverse (bool singExc) const throw (Iex::MathExc) if (pivotsize == 0) { if (singExc) - throw ::Imath::SingMatrixExc ("Cannot invert singular matrix."); + throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix."); return Matrix44(); } @@ -2782,7 +2775,7 @@ Matrix44::gjInverse (bool singExc) const throw (Iex::MathExc) if ((f = t[i][i]) == 0) { if (singExc) - throw ::Imath::SingMatrixExc ("Cannot invert singular matrix."); + throw ::IMATH_INTERNAL_NAMESPACE::SingMatrixExc ("Cannot invert singular matrix."); return Matrix44(); } @@ -2810,7 +2803,7 @@ Matrix44::gjInverse (bool singExc) const throw (Iex::MathExc) template const Matrix44 & -Matrix44::invert (bool singExc) throw (Iex::MathExc) +Matrix44::invert (bool singExc) { *this = inverse (singExc); return *this; @@ -2818,7 +2811,7 @@ Matrix44::invert (bool singExc) throw (Iex::MathExc) template Matrix44 -Matrix44::inverse (bool singExc) const throw (Iex::MathExc) +Matrix44::inverse (bool singExc) const { if (x[0][3] != 0 || x[1][3] != 0 || x[2][3] != 0 || x[3][3] != 1) return gjInverse(singExc); @@ -2845,7 +2838,7 @@ Matrix44::inverse (bool singExc) const throw (Iex::MathExc) T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; - if (Imath::abs (r) >= 1) + if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { @@ -2857,13 +2850,13 @@ Matrix44::inverse (bool singExc) const throw (Iex::MathExc) } else { - T mr = Imath::abs (r) / limits::smallest(); + T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / limits::smallest(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { - if (mr > Imath::abs (s[i][j])) + if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } @@ -2933,25 +2926,25 @@ const Matrix44 & Matrix44::setEulerAngles (const Vec3& r) { S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx; - + cos_rz = Math::cos (r[2]); cos_ry = Math::cos (r[1]); cos_rx = Math::cos (r[0]); - + sin_rz = Math::sin (r[2]); sin_ry = Math::sin (r[1]); sin_rx = Math::sin (r[0]); - + x[0][0] = cos_rz * cos_ry; x[0][1] = sin_rz * cos_ry; x[0][2] = -sin_ry; x[0][3] = 0; - + x[1][0] = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx; x[1][1] = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx; x[1][2] = cos_ry * sin_rx; x[1][3] = 0; - + x[2][0] = sin_rz * sin_rx + cos_rz * sin_ry * cos_rx; x[2][1] = -cos_rz * sin_rx + sin_rz * sin_ry * cos_rx; x[2][2] = cos_ry * cos_rx; @@ -3010,7 +3003,7 @@ Matrix44::rotate (const Vec3 &r) cos_rz = Math::cos (r[2]); cos_ry = Math::cos (r[1]); cos_rx = Math::cos (r[0]); - + sin_rz = Math::sin (r[2]); sin_ry = Math::sin (r[1]); sin_rx = Math::sin (r[0]); @@ -3205,10 +3198,10 @@ const Matrix44 & Matrix44::shear (const Vec3 &h) { // - // In this case, we don't need a temp. copy of the matrix - // because we never use a value on the RHS after we've + // In this case, we don't need a temp. copy of the matrix + // because we never use a value on the RHS after we've // changed it on the LHS. - // + // for (int i=0; i < 4; i++) { @@ -3251,13 +3244,13 @@ operator << (std::ostream &s, const Matrix33 &m) if (s.flags() & std::ios_base::fixed) { s.setf (std::ios_base::showpoint); - width = s.precision() + 5; + width = static_cast(s.precision()) + 5; } else { s.setf (std::ios_base::scientific); s.setf (std::ios_base::showpoint); - width = s.precision() + 8; + width = static_cast(s.precision()) + 8; } s << "(" << std::setw (width) << m[0][0] << @@ -3286,13 +3279,13 @@ operator << (std::ostream &s, const Matrix44 &m) if (s.flags() & std::ios_base::fixed) { s.setf (std::ios_base::showpoint); - width = s.precision() + 5; + width = static_cast(s.precision()) + 5; } else { s.setf (std::ios_base::scientific); s.setf (std::ios_base::showpoint); - width = s.precision() + 8; + width = static_cast(s.precision()) + 8; } s << "(" << std::setw (width) << m[0][0] << @@ -3435,8 +3428,6 @@ operator * (const Vec4 &v, const Matrix44 &m) return Vec4 (x, y, z, w); } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT - - -#endif +#endif // INCLUDED_IMATHMATRIX_H diff --git a/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp b/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp index 7ddc64968f..0cafd5c060 100644 --- a/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp +++ b/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -44,7 +44,7 @@ #include "ImathMatrixAlgo.h" #include -#include // for std::max() +#include #if defined(OPENEXR_DLL) #define EXPORT_CONST __declspec(dllexport) @@ -52,25 +52,25 @@ #define EXPORT_CONST const #endif -namespace Imath { +IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER EXPORT_CONST M33f identity33f ( 1, 0, 0, - 0, 1, 0, - 0, 0, 1); + 0, 1, 0, + 0, 0, 1); EXPORT_CONST M33d identity33d ( 1, 0, 0, - 0, 1, 0, - 0, 0, 1); + 0, 1, 0, + 0, 0, 1); EXPORT_CONST M44f identity44f ( 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); EXPORT_CONST M44d identity44d ( 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); namespace { @@ -166,7 +166,7 @@ procrustesRotationAndTranslation (const Vec3* A, const Vec3* B, const T* w M33d U, V; V3d S; - jacobiSVD (C, U, S, V, Imath::limits::epsilon(), true); + jacobiSVD (C, U, S, V, IMATH_INTERNAL_NAMESPACE::limits::epsilon(), true); // We want Q.transposed() here since we are going to be using it in the // Imath style (multiplying vectors on the right, v' = v*A^T): @@ -176,10 +176,10 @@ procrustesRotationAndTranslation (const Vec3* A, const Vec3* B, const T* w if (doScale && numPoints > 1) { // Finding a uniform scale: let us assume the Q is completely fixed - // at this point (solving for both simultaneously seems much harder). + // at this point (solving for both simultaneously seems much harder). // We are trying to compute (again, per Golub and van Loan) // min || s*A*Q - B ||_F - // Notice that we've jammed a uniform scale in front of the Q. + // Notice that we've jammed a uniform scale in front of the Q. // Now, the Frobenius norm (the least squares norm over matrices) // has the neat property that it is equivalent to minimizing the trace // of M^T*M (see your friendly neighborhood linear algebra text for a @@ -232,7 +232,7 @@ procrustesRotationAndTranslation (const Vec3* A, const Vec3* B, const T* w // [ 0 1 0 tb ] [ s*Q 0 ] [ 0 1 0 -ta ] = [ 0 1 0 tb ] [ s*Q -s*Q*ta ] = [ Q tb-s*Q*ta ] // [ 0 0 1 | ] [ 0 ] [ 0 0 1 | ] [ 0 0 1 | ] [ | ] [ ] // [ 0 0 0 1 ] [ 0 0 0 1 ] [ 0 0 0 1 ] [ 0 0 0 1 ] [ 0 0 0 1 ] [ 0 0 0 1 ] - // (ofc the whole thing is transposed for Imath). + // (ofc the whole thing is transposed for Imath). const V3d translate = Bcenter - s*Acenter*Qt; return M44d (s*Qt.x[0][0], s*Qt.x[0][1], s*Qt.x[0][2], T(0), @@ -249,10 +249,10 @@ procrustesRotationAndTranslation (const Vec3* A, const Vec3* B, const size } // procrustesRotationAndTranslation -template M44d procrustesRotationAndTranslation (const V3d* from, const V3d* to, const size_t numPoints, const bool doScale); -template M44d procrustesRotationAndTranslation (const V3f* from, const V3f* to, const size_t numPoints, const bool doScale); -template M44d procrustesRotationAndTranslation (const V3d* from, const V3d* to, const double* weights, const size_t numPoints, const bool doScale); -template M44d procrustesRotationAndTranslation (const V3f* from, const V3f* to, const float* weights, const size_t numPoints, const bool doScale); +template IMATH_EXPORT M44d procrustesRotationAndTranslation (const V3d* from, const V3d* to, const size_t numPoints, const bool doScale); +template IMATH_EXPORT M44d procrustesRotationAndTranslation (const V3f* from, const V3f* to, const size_t numPoints, const bool doScale); +template IMATH_EXPORT M44d procrustesRotationAndTranslation (const V3d* from, const V3d* to, const double* weights, const size_t numPoints, const bool doScale); +template IMATH_EXPORT M44d procrustesRotationAndTranslation (const V3f* from, const V3f* to, const float* weights, const size_t numPoints, const bool doScale); namespace @@ -266,10 +266,10 @@ namespace // J * A // for the Jacobi rotation J and the matrix A. This is efficient because we // only need to touch exactly the 2 columns that are affected, so we never -// need to explicitly construct the J matrix. +// need to explicitly construct the J matrix. template void -jacobiRotateRight (Imath::Matrix33& A, +jacobiRotateRight (IMATH_INTERNAL_NAMESPACE::Matrix33& A, const T c, const T s) { @@ -284,7 +284,7 @@ jacobiRotateRight (Imath::Matrix33& A, template void -jacobiRotateRight (Imath::Matrix44& A, +jacobiRotateRight (IMATH_INTERNAL_NAMESPACE::Matrix44& A, const int j, const int k, const T c, @@ -313,12 +313,12 @@ jacobiRotateRight (Imath::Matrix44& A, // 'Computation of the Singular Value Decomposition using Mesh-Connected Processors' // by Richard P. Brent, Franklin T. Luk, and Charles Van Loan // It breaks the computation into two steps: the first symmetrizes the matrix, -// and the second diagonalizes the symmetric matrix. +// and the second diagonalizes the symmetric matrix. template bool -twoSidedJacobiRotation (Imath::Matrix33& A, - Imath::Matrix33& U, - Imath::Matrix33& V, +twoSidedJacobiRotation (IMATH_INTERNAL_NAMESPACE::Matrix33& A, + IMATH_INTERNAL_NAMESPACE::Matrix33& U, + IMATH_INTERNAL_NAMESPACE::Matrix33& V, const T tol) { // Load everything into local variables to make things easier on the @@ -403,7 +403,7 @@ twoSidedJacobiRotation (Imath::Matrix33& A, const T d_2 = s_1*(w*s_2 + x*c_2) + c_1*(y*s_2 + z*c_2); // For the entries we just zeroed out, we'll just set them to 0, since - // they should be 0 up to machine precision. + // they should be 0 up to machine precision. A[j][j] = d_1; A[k][k] = d_2; A[k][j] = 0; @@ -416,7 +416,7 @@ twoSidedJacobiRotation (Imath::Matrix33& A, // [ -s1 c1 0 ] or [ 0 1 0 ] or [ 0 c1 s1 ] // [ 0 0 1 ] [ -s1 0 c1 ] [ 0 -s1 c1 ] // This has the effect of adding the (weighted) ith and jth _rows_ to - // each other. + // each other. const T tau1 = A[j][l]; const T tau2 = A[k][l]; A[j][l] = c_1 * tau1 - s_1 * tau2; @@ -429,7 +429,7 @@ twoSidedJacobiRotation (Imath::Matrix33& A, // [ -s2 c2 0 ] or [ 0 1 0 ] or [ 0 c2 s2 ] // [ 0 0 1 ] [ -s2 0 c2 ] [ 0 -s2 c2 ] // This has the effect of adding the (weighted) ith and jth _columns_ to - // each other. + // each other. const T tau1 = A[l][j]; const T tau2 = A[l][k]; A[l][j] = c_2 * tau1 - s_2 * tau2; @@ -437,7 +437,7 @@ twoSidedJacobiRotation (Imath::Matrix33& A, } // Now apply the rotations to U and V: - // Remember that we have + // Remember that we have // R1^T * A * R2 = D // This is in the 2x2 case, but after doing a bunch of these // we will get something like this for the 3x3 case: @@ -455,11 +455,11 @@ twoSidedJacobiRotation (Imath::Matrix33& A, template bool -twoSidedJacobiRotation (Imath::Matrix44& A, +twoSidedJacobiRotation (IMATH_INTERNAL_NAMESPACE::Matrix44& A, int j, int k, - Imath::Matrix44& U, - Imath::Matrix44& V, + IMATH_INTERNAL_NAMESPACE::Matrix44& U, + IMATH_INTERNAL_NAMESPACE::Matrix44& V, const T tol) { // Load everything into local variables to make things easier on the @@ -544,7 +544,7 @@ twoSidedJacobiRotation (Imath::Matrix44& A, const T d_2 = s_1*(w*s_2 + x*c_2) + c_1*(y*s_2 + z*c_2); // For the entries we just zeroed out, we'll just set them to 0, since - // they should be 0 up to machine precision. + // they should be 0 up to machine precision. A[j][j] = d_1; A[k][k] = d_2; A[k][j] = 0; @@ -567,7 +567,7 @@ twoSidedJacobiRotation (Imath::Matrix44& A, // j k // // This has the effect of adding the (weighted) ith and jth _rows_ to - // each other. + // each other. const T tau1 = A[j][l]; const T tau2 = A[k][l]; A[j][l] = c_1 * tau1 - s_1 * tau2; @@ -591,7 +591,7 @@ twoSidedJacobiRotation (Imath::Matrix44& A, // j k // // This has the effect of adding the (weighted) ith and jth _columns_ to - // each other. + // each other. const T tau1 = A[l][j]; const T tau2 = A[l][k]; A[l][j] = c_2 * tau1 - s_2 * tau2; @@ -599,7 +599,7 @@ twoSidedJacobiRotation (Imath::Matrix44& A, } // Now apply the rotations to U and V: - // Remember that we have + // Remember that we have // R1^T * A * R2 = D // This is in the 2x2 case, but after doing a bunch of these // we will get something like this for the 3x3 case: @@ -617,7 +617,7 @@ twoSidedJacobiRotation (Imath::Matrix44& A, template void -swapColumns (Imath::Matrix33& A, int j, int k) +swapColumns (IMATH_INTERNAL_NAMESPACE::Matrix33& A, int j, int k) { for (int i = 0; i < 3; ++i) std::swap (A[i][j], A[i][k]); @@ -625,7 +625,7 @@ swapColumns (Imath::Matrix33& A, int j, int k) template T -maxOffDiag (const Imath::Matrix33& A) +maxOffDiag (const IMATH_INTERNAL_NAMESPACE::Matrix33& A) { T result = 0; result = std::max (result, std::abs (A[0][1])); @@ -639,7 +639,7 @@ maxOffDiag (const Imath::Matrix33& A) template T -maxOffDiag (const Imath::Matrix44& A) +maxOffDiag (const IMATH_INTERNAL_NAMESPACE::Matrix44& A) { T result = 0; for (int i = 0; i < 4; ++i) @@ -656,10 +656,10 @@ maxOffDiag (const Imath::Matrix44& A) template void -twoSidedJacobiSVD (Imath::Matrix33 A, - Imath::Matrix33& U, - Imath::Vec3& S, - Imath::Matrix33& V, +twoSidedJacobiSVD (IMATH_INTERNAL_NAMESPACE::Matrix33 A, + IMATH_INTERNAL_NAMESPACE::Matrix33& U, + IMATH_INTERNAL_NAMESPACE::Vec3& S, + IMATH_INTERNAL_NAMESPACE::Matrix33& V, const T tol, const bool forcePositiveDeterminant) { @@ -680,7 +680,7 @@ twoSidedJacobiSVD (Imath::Matrix33 A, // [-s1 c1 ] [ * *] [-s2 c2 ] = [* * *] // [ 1] [* * *] [ 1] [ * *] // However, if we keep doing this, we'll find that the off-diagonal entries - // converge to 0 fairly quickly (convergence should be roughly cubic). The + // converge to 0 fairly quickly (convergence should be roughly cubic). The // result is a diagonal A matrix and a bunch of orthogonal transforms: // [* * *] [* ] // L1 L2 ... Ln [* * *] Rn ... R2 R1 = [ * ] @@ -691,7 +691,7 @@ twoSidedJacobiSVD (Imath::Matrix33 A, // are extremely stable to compute and apply (this is why QR factorization // works so well, FWIW) and because (2) by applying everything to the original // matrix A instead of computing (A^T * A) we avoid any precision loss that - // would result from that. + // would result from that. U.makeIdentity(); V.makeIdentity(); @@ -770,7 +770,7 @@ twoSidedJacobiSVD (Imath::Matrix33 A, U[i][2] = -U[i][2]; S.z = -S.z; } - + if (V.determinant() < 0) { for (int i = 0; i < 3; ++i) @@ -782,10 +782,10 @@ twoSidedJacobiSVD (Imath::Matrix33 A, template void -twoSidedJacobiSVD (Imath::Matrix44 A, - Imath::Matrix44& U, - Imath::Vec4& S, - Imath::Matrix44& V, +twoSidedJacobiSVD (IMATH_INTERNAL_NAMESPACE::Matrix44 A, + IMATH_INTERNAL_NAMESPACE::Matrix44& U, + IMATH_INTERNAL_NAMESPACE::Vec4& S, + IMATH_INTERNAL_NAMESPACE::Matrix44& V, const T tol, const bool forcePositiveDeterminant) { @@ -837,8 +837,8 @@ twoSidedJacobiSVD (Imath::Matrix44 A, // Order the singular values from largest to smallest using insertion sort: for (int i = 1; i < 4; ++i) { - const Imath::Vec4 uCol (U[0][i], U[1][i], U[2][i], U[3][i]); - const Imath::Vec4 vCol (V[0][i], V[1][i], V[2][i], V[3][i]); + const IMATH_INTERNAL_NAMESPACE::Vec4 uCol (U[0][i], U[1][i], U[2][i], U[3][i]); + const IMATH_INTERNAL_NAMESPACE::Vec4 vCol (V[0][i], V[1][i], V[2][i], V[3][i]); const T sVal = S[i]; int j = i - 1; @@ -882,7 +882,7 @@ twoSidedJacobiSVD (Imath::Matrix44 A, U[i][3] = -U[i][3]; S[3] = -S[3]; } - + if (V.determinant() < 0) { for (int i = 0; i < 4; ++i) @@ -896,10 +896,10 @@ twoSidedJacobiSVD (Imath::Matrix44 A, template void -jacobiSVD (const Imath::Matrix33& A, - Imath::Matrix33& U, - Imath::Vec3& S, - Imath::Matrix33& V, +jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix33& A, + IMATH_INTERNAL_NAMESPACE::Matrix33& U, + IMATH_INTERNAL_NAMESPACE::Vec3& S, + IMATH_INTERNAL_NAMESPACE::Matrix33& V, const T tol, const bool forcePositiveDeterminant) { @@ -908,46 +908,46 @@ jacobiSVD (const Imath::Matrix33& A, template void -jacobiSVD (const Imath::Matrix44& A, - Imath::Matrix44& U, - Imath::Vec4& S, - Imath::Matrix44& V, +jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix44& A, + IMATH_INTERNAL_NAMESPACE::Matrix44& U, + IMATH_INTERNAL_NAMESPACE::Vec4& S, + IMATH_INTERNAL_NAMESPACE::Matrix44& V, const T tol, const bool forcePositiveDeterminant) { twoSidedJacobiSVD (A, U, S, V, tol, forcePositiveDeterminant); } -template void jacobiSVD (const Imath::Matrix33& A, - Imath::Matrix33& U, - Imath::Vec3& S, - Imath::Matrix33& V, - const float tol, - const bool forcePositiveDeterminant); -template void jacobiSVD (const Imath::Matrix33& A, - Imath::Matrix33& U, - Imath::Vec3& S, - Imath::Matrix33& V, - const double tol, - const bool forcePositiveDeterminant); -template void jacobiSVD (const Imath::Matrix44& A, - Imath::Matrix44& U, - Imath::Vec4& S, - Imath::Matrix44& V, - const float tol, - const bool forcePositiveDeterminant); -template void jacobiSVD (const Imath::Matrix44& A, - Imath::Matrix44& U, - Imath::Vec4& S, - Imath::Matrix44& V, - const double tol, - const bool forcePositiveDeterminant); +template IMATH_EXPORT void jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix33& A, + IMATH_INTERNAL_NAMESPACE::Matrix33& U, + IMATH_INTERNAL_NAMESPACE::Vec3& S, + IMATH_INTERNAL_NAMESPACE::Matrix33& V, + const float tol, + const bool forcePositiveDeterminant); +template IMATH_EXPORT void jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix33& A, + IMATH_INTERNAL_NAMESPACE::Matrix33& U, + IMATH_INTERNAL_NAMESPACE::Vec3& S, + IMATH_INTERNAL_NAMESPACE::Matrix33& V, + const double tol, + const bool forcePositiveDeterminant); +template IMATH_EXPORT void jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix44& A, + IMATH_INTERNAL_NAMESPACE::Matrix44& U, + IMATH_INTERNAL_NAMESPACE::Vec4& S, + IMATH_INTERNAL_NAMESPACE::Matrix44& V, + const float tol, + const bool forcePositiveDeterminant); +template IMATH_EXPORT void jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix44& A, + IMATH_INTERNAL_NAMESPACE::Matrix44& U, + IMATH_INTERNAL_NAMESPACE::Vec4& S, + IMATH_INTERNAL_NAMESPACE::Matrix44& V, + const double tol, + const bool forcePositiveDeterminant); namespace { template -inline +inline void jacobiRotateRight (TM& A, const typename TM::BaseType s, @@ -1006,7 +1006,7 @@ jacobiRotation (Matrix33& A, A[k][k] += h; // For the entries we just zeroed out, we'll just set them to 0, since - // they should be 0 up to machine precision. + // they should be 0 up to machine precision. A[j][k] = 0; // We only update upper triagnular elements of A, since @@ -1016,7 +1016,7 @@ jacobiRotation (Matrix33& A, const T nu1 = offd1; const T nu2 = offd2; offd1 = nu1 - s * (nu2 + tau * nu1); - offd2 = nu2 + s * (nu1 - tau * nu2); + offd2 = nu2 + s * (nu1 - tau * nu2); // Apply rotation to V jacobiRotateRight (V, s, tau); @@ -1039,7 +1039,7 @@ jacobiRotation (Matrix44& A, const T mu2 = T(2) * y; // Let's see if rho^(-1) = mu2 / mu1 is less than tol - // This test also checks if rho^2 will overflow + // This test also checks if rho^2 will overflow // when tol^(-1) < sqrt(limits::max()). if (std::abs(mu2) <= tol*std::abs(mu1)) { @@ -1066,7 +1066,7 @@ jacobiRotation (Matrix44& A, const T nu1 = offd1; const T nu2 = offd2; offd1 -= s * (nu2 + tau * nu1); - offd2 += s * (nu1 - tau * nu2); + offd2 += s * (nu1 - tau * nu2); } { @@ -1075,7 +1075,7 @@ jacobiRotation (Matrix44& A, const T nu1 = offd1; const T nu2 = offd2; offd1 -= s * (nu2 + tau * nu1); - offd2 += s * (nu1 - tau * nu2); + offd2 += s * (nu1 - tau * nu2); } jacobiRotateRight (V, s, tau); @@ -1120,8 +1120,8 @@ jacobiEigenSolver (Matrix33& A, { // Z is for accumulating small changes (h) to diagonal entries // of A for one sweep. Adding h's directly to A might cause - // a cancellation effect when h is relatively very small to - // the corresponding diagonal entry of A and + // a cancellation effect when h is relatively very small to + // the corresponding diagonal entry of A and // this will increase numerical errors Vec3 Z(0, 0, 0); ++numIter; @@ -1214,39 +1214,39 @@ minEigenVector (TM& A, TV& V) V[i] = MV[i][minIdx]; } -template void jacobiEigenSolver (Matrix33& A, - Vec3& S, - Matrix33& V, - const float tol); -template void jacobiEigenSolver (Matrix33& A, - Vec3& S, - Matrix33& V, - const double tol); -template void jacobiEigenSolver (Matrix44& A, - Vec4& S, - Matrix44& V, - const float tol); -template void jacobiEigenSolver (Matrix44& A, - Vec4& S, - Matrix44& V, - const double tol); - -template void maxEigenVector (Matrix33& A, - Vec3& S); -template void maxEigenVector (Matrix44& A, - Vec4& S); -template void maxEigenVector (Matrix33& A, - Vec3& S); -template void maxEigenVector (Matrix44& A, - Vec4& S); - -template void minEigenVector (Matrix33& A, - Vec3& S); -template void minEigenVector (Matrix44& A, - Vec4& S); -template void minEigenVector (Matrix33& A, - Vec3& S); -template void minEigenVector (Matrix44& A, - Vec4& S); - -} // namespace Imath +template IMATH_EXPORT void jacobiEigenSolver (Matrix33& A, + Vec3& S, + Matrix33& V, + const float tol); +template IMATH_EXPORT void jacobiEigenSolver (Matrix33& A, + Vec3& S, + Matrix33& V, + const double tol); +template IMATH_EXPORT void jacobiEigenSolver (Matrix44& A, + Vec4& S, + Matrix44& V, + const float tol); +template IMATH_EXPORT void jacobiEigenSolver (Matrix44& A, + Vec4& S, + Matrix44& V, + const double tol); + +template IMATH_EXPORT void maxEigenVector (Matrix33& A, + Vec3& S); +template IMATH_EXPORT void maxEigenVector (Matrix44& A, + Vec4& S); +template IMATH_EXPORT void maxEigenVector (Matrix33& A, + Vec3& S); +template IMATH_EXPORT void maxEigenVector (Matrix44& A, + Vec4& S); + +template IMATH_EXPORT void minEigenVector (Matrix33& A, + Vec3& S); +template IMATH_EXPORT void minEigenVector (Matrix44& A, + Vec4& S); +template IMATH_EXPORT void minEigenVector (Matrix33& A, + Vec3& S); +template IMATH_EXPORT void minEigenVector (Matrix44& A, + Vec4& S); + +IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/Imath/ImathMatrixAlgo.h b/3rdparty/openexr/Imath/ImathMatrixAlgo.h index 707b77dbc7..8e90b02cb4 100644 --- a/3rdparty/openexr/Imath/ImathMatrixAlgo.h +++ b/3rdparty/openexr/Imath/ImathMatrixAlgo.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -38,37 +38,27 @@ //------------------------------------------------------------------------- // -// This file contains algorithms applied to or in conjunction with -// transformation matrices (Imath::Matrix33 and Imath::Matrix44). -// The assumption made is that these functions are called much less -// often than the basic point functions or these functions require -// more support classes. +// This file contains algorithms applied to or in conjunction with +// transformation matrices (Imath::Matrix33 and Imath::Matrix44). +// The assumption made is that these functions are called much less +// often than the basic point functions or these functions require +// more support classes. // -// This file also defines a few predefined constant matrices. +// This file also defines a few predefined constant matrices. // //------------------------------------------------------------------------- +#include "ImathExport.h" #include "ImathMatrix.h" #include "ImathQuat.h" #include "ImathEuler.h" #include "ImathExc.h" #include "ImathVec.h" #include "ImathLimits.h" +#include "ImathNamespace.h" #include - -#ifdef OPENEXR_DLL - #ifdef IMATH_EXPORTS - #define IMATH_EXPORT_CONST extern __declspec(dllexport) - #else - #define IMATH_EXPORT_CONST extern __declspec(dllimport) - #endif -#else - #define IMATH_EXPORT_CONST extern const -#endif - - -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER //------------------ // Identity matrices @@ -81,11 +71,11 @@ IMATH_EXPORT_CONST M44d identity44d; //---------------------------------------------------------------------- // Extract scale, shear, rotation, and translation values from a matrix: -// +// // Notes: // // This implementation follows the technique described in the paper by -// Spencer W. Thomas in the Graphics Gems II article: "Decomposing a +// Spencer W. Thomas in the Graphics Gems II article: "Decomposing a // Matrix into Simple Transformations", p. 320. // // - Some of the functions below have an optional exc parameter @@ -101,23 +91,23 @@ IMATH_EXPORT_CONST M44d identity44d; // removeScaling (m) returns false, m is unchanged // sansScalingAndShear (m) returns m // removeScalingAndShear (m) returns false, m is unchanged -// extractAndRemoveScalingAndShear (m, s, h) -// returns false, m is unchanged, +// extractAndRemoveScalingAndShear (m, s, h) +// returns false, m is unchanged, // (sh) are invalid // checkForZeroScaleInRow () returns false // extractSHRT (m, s, h, r, t) returns false, (shrt) are invalid // -// - Functions extractEuler(), extractEulerXYZ() and extractEulerZYX() -// assume that the matrix does not include shear or non-uniform scaling, -// but they do not examine the matrix to verify this assumption. -// Matrices with shear or non-uniform scaling are likely to produce -// meaningless results. Therefore, you should use the +// - Functions extractEuler(), extractEulerXYZ() and extractEulerZYX() +// assume that the matrix does not include shear or non-uniform scaling, +// but they do not examine the matrix to verify this assumption. +// Matrices with shear or non-uniform scaling are likely to produce +// meaningless results. Therefore, you should use the // removeScalingAndShear() routine, if necessary, prior to calling // extractEuler...() . // // - All functions assume that the matrix does not include perspective -// transformation(s), but they do not examine the matrix to verify -// this assumption. Matrices with perspective transformations are +// transformation(s), but they do not examine the matrix to verify +// this assumption. Matrices with perspective transformations are // likely to produce meaningless results. // //---------------------------------------------------------------------- @@ -127,86 +117,86 @@ IMATH_EXPORT_CONST M44d identity44d; // Declarations for 4x4 matrix. // -template bool extractScaling +template bool extractScaling (const Matrix44 &mat, - Vec3 &scl, - bool exc = true); + Vec3 &scl, + bool exc = true); + +template Matrix44 sansScaling (const Matrix44 &mat, + bool exc = true); -template Matrix44 sansScaling (const Matrix44 &mat, - bool exc = true); - -template bool removeScaling - (Matrix44 &mat, - bool exc = true); +template bool removeScaling + (Matrix44 &mat, + bool exc = true); -template bool extractScalingAndShear +template bool extractScalingAndShear (const Matrix44 &mat, - Vec3 &scl, - Vec3 &shr, - bool exc = true); - -template Matrix44 sansScalingAndShear - (const Matrix44 &mat, - bool exc = true); - -template void sansScalingAndShear + Vec3 &scl, + Vec3 &shr, + bool exc = true); + +template Matrix44 sansScalingAndShear + (const Matrix44 &mat, + bool exc = true); + +template void sansScalingAndShear (Matrix44 &result, - const Matrix44 &mat, - bool exc = true); + const Matrix44 &mat, + bool exc = true); -template bool removeScalingAndShear +template bool removeScalingAndShear (Matrix44 &mat, - bool exc = true); + bool exc = true); template bool extractAndRemoveScalingAndShear (Matrix44 &mat, - Vec3 &scl, - Vec3 &shr, - bool exc = true); + Vec3 &scl, + Vec3 &shr, + bool exc = true); -template void extractEulerXYZ +template void extractEulerXYZ (const Matrix44 &mat, - Vec3 &rot); + Vec3 &rot); -template void extractEulerZYX +template void extractEulerZYX (const Matrix44 &mat, - Vec3 &rot); + Vec3 &rot); template Quat extractQuat (const Matrix44 &mat); -template bool extractSHRT +template bool extractSHRT (const Matrix44 &mat, - Vec3 &s, - Vec3 &h, - Vec3 &r, - Vec3 &t, - bool exc /*= true*/, - typename Euler::Order rOrder); - -template bool extractSHRT + Vec3 &s, + Vec3 &h, + Vec3 &r, + Vec3 &t, + bool exc /*= true*/, + typename Euler::Order rOrder); + +template bool extractSHRT (const Matrix44 &mat, - Vec3 &s, - Vec3 &h, - Vec3 &r, - Vec3 &t, - bool exc = true); + Vec3 &s, + Vec3 &h, + Vec3 &r, + Vec3 &t, + bool exc = true); -template bool extractSHRT +template bool extractSHRT (const Matrix44 &mat, - Vec3 &s, - Vec3 &h, - Euler &r, - Vec3 &t, - bool exc = true); + Vec3 &s, + Vec3 &h, + Euler &r, + Vec3 &t, + bool exc = true); // // Internal utility function. // template bool checkForZeroScaleInRow - (const T &scl, - const Vec3 &row, - bool exc = true); + (const T &scl, + const Vec3 &row, + bool exc = true); template Matrix44 outerProduct ( const Vec4 &a, @@ -219,45 +209,45 @@ template Matrix44 outerProduct // template Matrix44 rotationMatrix (const Vec3 &fromDirection, - const Vec3 &toDirection); + const Vec3 &toDirection); // -// Returns a matrix that rotates the "fromDir" vector -// so that it points towards "toDir". You may also -// specify that you want the up vector to be pointing +// Returns a matrix that rotates the "fromDir" vector +// so that it points towards "toDir". You may also +// specify that you want the up vector to be pointing // in a certain direction "upDir". // -template Matrix44 rotationMatrixWithUpDir +template Matrix44 rotationMatrixWithUpDir (const Vec3 &fromDir, - const Vec3 &toDir, - const Vec3 &upDir); + const Vec3 &toDir, + const Vec3 &upDir); // -// Constructs a matrix that rotates the z-axis so that it -// points towards "targetDir". You must also specify -// that you want the up vector to be pointing in a +// Constructs a matrix that rotates the z-axis so that it +// points towards "targetDir". You must also specify +// that you want the up vector to be pointing in a // certain direction "upDir". // // Notes: The following degenerate cases are handled: -// (a) when the directions given by "toDir" and "upDir" +// (a) when the directions given by "toDir" and "upDir" // are parallel or opposite; // (the direction vectors must have a non-zero cross product) // (b) when any of the given direction vectors have zero length // -template void alignZAxisWithTargetDir +template void alignZAxisWithTargetDir (Matrix44 &result, - Vec3 targetDir, - Vec3 upDir); + Vec3 targetDir, + Vec3 upDir); // Compute an orthonormal direct frame from : a position, an x axis direction and a normal to the y axis // If the x axis and normal are perpendicular, then the normal will have the same direction as the z axis. -// Inputs are : +// Inputs are : // -the position of the frame // -the x axis direction of the frame // -a normal to the y axis of the frame @@ -289,7 +279,7 @@ template Matrix44 addOffset( const Matrix44& inMat, // -Matrix B // Return Matrix A with tweaked rotation/scale template Matrix44 computeRSMatrix( bool keepRotateA, - bool keepScaleA, + bool keepScaleA, const Matrix44& A, const Matrix44& B); @@ -297,58 +287,58 @@ template Matrix44 computeRSMatrix( bool keepRotateA, //---------------------------------------------------------------------- -// +// // Declarations for 3x3 matrix. // - -template bool extractScaling + +template bool extractScaling (const Matrix33 &mat, - Vec2 &scl, - bool exc = true); - -template Matrix33 sansScaling (const Matrix33 &mat, - bool exc = true); - -template bool removeScaling - (Matrix33 &mat, - bool exc = true); + Vec2 &scl, + bool exc = true); + +template Matrix33 sansScaling (const Matrix33 &mat, + bool exc = true); -template bool extractScalingAndShear - (const Matrix33 &mat, - Vec2 &scl, - T &h, - bool exc = true); +template bool removeScaling + (Matrix33 &mat, + bool exc = true); -template Matrix33 sansScalingAndShear +template bool extractScalingAndShear (const Matrix33 &mat, - bool exc = true); - -template bool removeScalingAndShear + Vec2 &scl, + T &h, + bool exc = true); + +template Matrix33 sansScalingAndShear + (const Matrix33 &mat, + bool exc = true); + +template bool removeScalingAndShear (Matrix33 &mat, - bool exc = true); + bool exc = true); template bool extractAndRemoveScalingAndShear (Matrix33 &mat, - Vec2 &scl, - T &shr, - bool exc = true); + Vec2 &scl, + T &shr, + bool exc = true); template void extractEuler (const Matrix33 &mat, - T &rot); + T &rot); template bool extractSHRT (const Matrix33 &mat, - Vec2 &s, - T &h, - T &r, - Vec2 &t, - bool exc = true); + Vec2 &s, + T &h, + T &r, + Vec2 &t, + bool exc = true); template bool checkForZeroScaleInRow - (const T &scl, - const Vec2 &row, - bool exc = true); + (const T &scl, + const Vec2 &row, + bool exc = true); template Matrix33 outerProduct ( const Vec3 &a, @@ -368,8 +358,8 @@ extractScaling (const Matrix44 &mat, Vec3 &scl, bool exc) Matrix44 M (mat); if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) - return false; - + return false; + return true; } @@ -384,10 +374,10 @@ sansScaling (const Matrix44 &mat, bool exc) Vec3 tran; if (! extractSHRT (mat, scl, shr, rot, tran, exc)) - return mat; + return mat; Matrix44 M; - + M.translate (tran); M.rotate (rot); M.shear (shr); @@ -406,7 +396,7 @@ removeScaling (Matrix44 &mat, bool exc) Vec3 tran; if (! extractSHRT (mat, scl, shr, rot, tran, exc)) - return false; + return false; mat.makeIdentity (); mat.translate (tran); @@ -419,14 +409,14 @@ removeScaling (Matrix44 &mat, bool exc) template bool -extractScalingAndShear (const Matrix44 &mat, - Vec3 &scl, Vec3 &shr, bool exc) +extractScalingAndShear (const Matrix44 &mat, + Vec3 &scl, Vec3 &shr, bool exc) { Matrix44 M (mat); if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) - return false; - + return false; + return true; } @@ -440,8 +430,8 @@ sansScalingAndShear (const Matrix44 &mat, bool exc) Matrix44 M (mat); if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) - return mat; - + return mat; + return M; } @@ -454,7 +444,7 @@ sansScalingAndShear (Matrix44 &result, const Matrix44 &mat, bool exc) Vec3 shr; if (! extractAndRemoveScalingAndShear (result, scl, shr, exc)) - result = mat; + result = mat; } @@ -466,20 +456,20 @@ removeScalingAndShear (Matrix44 &mat, bool exc) Vec3 shr; if (! extractAndRemoveScalingAndShear (mat, scl, shr, exc)) - return false; - + return false; + return true; } template bool -extractAndRemoveScalingAndShear (Matrix44 &mat, - Vec3 &scl, Vec3 &shr, bool exc) +extractAndRemoveScalingAndShear (Matrix44 &mat, + Vec3 &scl, Vec3 &shr, bool exc) { // // This implementation follows the technique described in the paper by - // Spencer W. Thomas in the Graphics Gems II article: "Decomposing a + // Spencer W. Thomas in the Graphics Gems II article: "Decomposing a // Matrix into Simple Transformations", p. 320. // @@ -488,34 +478,34 @@ extractAndRemoveScalingAndShear (Matrix44 &mat, row[0] = Vec3 (mat[0][0], mat[0][1], mat[0][2]); row[1] = Vec3 (mat[1][0], mat[1][1], mat[1][2]); row[2] = Vec3 (mat[2][0], mat[2][1], mat[2][2]); - + T maxVal = 0; for (int i=0; i < 3; i++) - for (int j=0; j < 3; j++) - if (Imath::abs (row[i][j]) > maxVal) - maxVal = Imath::abs (row[i][j]); + for (int j=0; j < 3; j++) + if (IMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal) + maxVal = IMATH_INTERNAL_NAMESPACE::abs (row[i][j]); // // We normalize the 3x3 matrix here. // It was noticed that this can improve numerical stability significantly, // especially when many of the upper 3x3 matrix's coefficients are very - // close to zero; we correct for this step at the end by multiplying the - // scaling factors by maxVal at the end (shear and rotation are not + // close to zero; we correct for this step at the end by multiplying the + // scaling factors by maxVal at the end (shear and rotation are not // affected by the normalization). if (maxVal != 0) { - for (int i=0; i < 3; i++) - if (! checkForZeroScaleInRow (maxVal, row[i], exc)) - return false; - else - row[i] /= maxVal; + for (int i=0; i < 3; i++) + if (! checkForZeroScaleInRow (maxVal, row[i], exc)) + return false; + else + row[i] /= maxVal; } - // Compute X scale factor. + // Compute X scale factor. scl.x = row[0].length (); if (! checkForZeroScaleInRow (scl.x, row[0], exc)) - return false; + return false; // Normalize first row. row[0] /= scl.x; @@ -537,10 +527,10 @@ extractAndRemoveScalingAndShear (Matrix44 &mat, // Now, compute Y scale. scl.y = row[1].length (); if (! checkForZeroScaleInRow (scl.y, row[1], exc)) - return false; + return false; // Normalize 2nd row and correct the XY shear factor for Y scaling. - row[1] /= scl.y; + row[1] /= scl.y; shr[0] /= scl.y; // Compute XZ and YZ shears, orthogonalize 3rd row. @@ -552,7 +542,7 @@ extractAndRemoveScalingAndShear (Matrix44 &mat, // Next, get Z scale. scl.z = row[2].length (); if (! checkForZeroScaleInRow (scl.z, row[2], exc)) - return false; + return false; // Normalize 3rd row and correct the XZ and YZ shear factors for Z scaling. row[2] /= scl.z; @@ -563,23 +553,23 @@ extractAndRemoveScalingAndShear (Matrix44 &mat, // Check for a coordinate system flip. If the determinant // is less than zero, then negate the matrix and the scaling factors. if (row[0].dot (row[1].cross (row[2])) < 0) - for (int i=0; i < 3; i++) - { - scl[i] *= -1; - row[i] *= -1; - } + for (int i=0; i < 3; i++) + { + scl[i] *= -1; + row[i] *= -1; + } // Copy over the orthonormal rows into the returned matrix. // The upper 3x3 matrix in mat is now a rotation matrix. for (int i=0; i < 3; i++) { - mat[i][0] = row[i][0]; - mat[i][1] = row[i][1]; - mat[i][2] = row[i][2]; + mat[i][0] = row[i][0]; + mat[i][1] = row[i][1]; + mat[i][2] = row[i][2]; } - // Correct the scaling factors for the normalization step that we - // performed above; shear and rotation are not affected by the + // Correct the scaling factors for the normalization step that we + // performed above; shear and rotation are not affected by the // normalization. scl *= maxVal; @@ -603,14 +593,14 @@ extractEulerXYZ (const Matrix44 &mat, Vec3 &rot) j.normalize(); k.normalize(); - Matrix44 M (i[0], i[1], i[2], 0, - j[0], j[1], j[2], 0, - k[0], k[1], k[2], 0, - 0, 0, 0, 1); + Matrix44 M (i[0], i[1], i[2], 0, + j[0], j[1], j[2], 0, + k[0], k[1], k[2], 0, + 0, 0, 0, 1); // // Extract the first angle, rot.x. - // + // rot.x = Math::atan2 (M[1][2], M[2][2]); @@ -650,14 +640,14 @@ extractEulerZYX (const Matrix44 &mat, Vec3 &rot) j.normalize(); k.normalize(); - Matrix44 M (i[0], i[1], i[2], 0, - j[0], j[1], j[2], 0, - k[0], k[1], k[2], 0, - 0, 0, 0, 1); + Matrix44 M (i[0], i[1], i[2], 0, + j[0], j[1], j[2], 0, + k[0], k[1], k[2], 0, + 0, 0, 0, 1); // // Extract the first angle, rot.x. - // + // rot.x = -Math::atan2 (M[1][0], M[0][0]); @@ -704,21 +694,21 @@ extractQuat (const Matrix44 &mat) quat.v.x = (mat[1][2] - mat[2][1]) * s; quat.v.y = (mat[2][0] - mat[0][2]) * s; quat.v.z = (mat[0][1] - mat[1][0]) * s; - } - else { + } + else { // diagonal is negative i = 0; - if (mat[1][1] > mat[0][0]) + if (mat[1][1] > mat[0][0]) i=1; - if (mat[2][2] > mat[i][i]) + if (mat[2][2] > mat[i][i]) i=2; - + j = nxt[i]; k = nxt[j]; s = Math::sqrt ((mat[i][i] - (mat[j][j] + mat[k][k])) + T(1.0)); - + q[i] = s * T(0.5); - if (s != T(0.0)) + if (s != T(0.0)) s = T(0.5) / s; q[3] = (mat[j][k] - mat[k][j]) * s; @@ -735,20 +725,20 @@ extractQuat (const Matrix44 &mat) } template -bool +bool extractSHRT (const Matrix44 &mat, - Vec3 &s, - Vec3 &h, - Vec3 &r, - Vec3 &t, - bool exc /* = true */ , - typename Euler::Order rOrder /* = Euler::XYZ */ ) + Vec3 &s, + Vec3 &h, + Vec3 &r, + Vec3 &t, + bool exc /* = true */ , + typename Euler::Order rOrder /* = Euler::XYZ */ ) { Matrix44 rot; rot = mat; if (! extractAndRemoveScalingAndShear (rot, s, h, exc)) - return false; + return false; extractEulerXYZ (rot, r); @@ -758,55 +748,55 @@ extractSHRT (const Matrix44 &mat, if (rOrder != Euler::XYZ) { - Imath::Euler eXYZ (r, Imath::Euler::XYZ); - Imath::Euler e (eXYZ, rOrder); - r = e.toXYZVector (); + IMATH_INTERNAL_NAMESPACE::Euler eXYZ (r, IMATH_INTERNAL_NAMESPACE::Euler::XYZ); + IMATH_INTERNAL_NAMESPACE::Euler e (eXYZ, rOrder); + r = e.toXYZVector (); } return true; } template -bool +bool extractSHRT (const Matrix44 &mat, - Vec3 &s, - Vec3 &h, - Vec3 &r, - Vec3 &t, - bool exc) + Vec3 &s, + Vec3 &h, + Vec3 &r, + Vec3 &t, + bool exc) { - return extractSHRT(mat, s, h, r, t, exc, Imath::Euler::XYZ); + return extractSHRT(mat, s, h, r, t, exc, IMATH_INTERNAL_NAMESPACE::Euler::XYZ); } template -bool +bool extractSHRT (const Matrix44 &mat, - Vec3 &s, - Vec3 &h, - Euler &r, - Vec3 &t, - bool exc /* = true */) + Vec3 &s, + Vec3 &h, + Euler &r, + Vec3 &t, + bool exc /* = true */) { return extractSHRT (mat, s, h, r, t, exc, r.order ()); } -template -bool -checkForZeroScaleInRow (const T& scl, - const Vec3 &row, - bool exc /* = true */ ) +template +bool +checkForZeroScaleInRow (const T& scl, + const Vec3 &row, + bool exc /* = true */ ) { for (int i = 0; i < 3; i++) { - if ((abs (scl) < 1 && abs (row[i]) >= limits::max() * abs (scl))) - { - if (exc) - throw Imath::ZeroScaleExc ("Cannot remove zero scaling " - "from matrix."); - else - return false; - } + if ((abs (scl) < 1 && abs (row[i]) >= limits::max() * abs (scl))) + { + if (exc) + throw IMATH_INTERNAL_NAMESPACE::ZeroScaleExc ("Cannot remove zero scaling " + "from matrix."); + else + return false; + } } return true; @@ -833,34 +823,34 @@ rotationMatrix (const Vec3 &from, const Vec3 &to) template -Matrix44 +Matrix44 rotationMatrixWithUpDir (const Vec3 &fromDir, - const Vec3 &toDir, - const Vec3 &upDir) + const Vec3 &toDir, + const Vec3 &upDir) { // - // The goal is to obtain a rotation matrix that takes - // "fromDir" to "toDir". We do this in two steps and - // compose the resulting rotation matrices; + // The goal is to obtain a rotation matrix that takes + // "fromDir" to "toDir". We do this in two steps and + // compose the resulting rotation matrices; // (a) rotate "fromDir" into the z-axis // (b) rotate the z-axis into "toDir" // // The from direction must be non-zero; but we allow zero to and up dirs. if (fromDir.length () == 0) - return Matrix44 (); + return Matrix44 (); else { - Matrix44 zAxis2FromDir( Imath::UNINITIALIZED ); - alignZAxisWithTargetDir (zAxis2FromDir, fromDir, Vec3 (0, 1, 0)); + Matrix44 zAxis2FromDir( IMATH_INTERNAL_NAMESPACE::UNINITIALIZED ); + alignZAxisWithTargetDir (zAxis2FromDir, fromDir, Vec3 (0, 1, 0)); - Matrix44 fromDir2zAxis = zAxis2FromDir.transposed (); + Matrix44 fromDir2zAxis = zAxis2FromDir.transposed (); + + Matrix44 zAxis2ToDir( IMATH_INTERNAL_NAMESPACE::UNINITIALIZED ); + alignZAxisWithTargetDir (zAxis2ToDir, toDir, upDir); - Matrix44 zAxis2ToDir( Imath::UNINITIALIZED ); - alignZAxisWithTargetDir (zAxis2ToDir, toDir, upDir); - - return fromDir2zAxis * zAxis2ToDir; + return fromDir2zAxis * zAxis2ToDir; } } @@ -874,61 +864,61 @@ alignZAxisWithTargetDir (Matrix44 &result, Vec3 targetDir, Vec3 upDir) // if ( targetDir.length () == 0 ) - targetDir = Vec3 (0, 0, 1); + targetDir = Vec3 (0, 0, 1); // // Ensure that the up direction is non-zero. // if ( upDir.length () == 0 ) - upDir = Vec3 (0, 1, 0); + upDir = Vec3 (0, 1, 0); // - // Check for degeneracies. If the upDir and targetDir are parallel + // Check for degeneracies. If the upDir and targetDir are parallel // or opposite, then compute a new, arbitrary up direction that is // not parallel or opposite to the targetDir. // if (upDir.cross (targetDir).length () == 0) { - upDir = targetDir.cross (Vec3 (1, 0, 0)); - if (upDir.length() == 0) - upDir = targetDir.cross(Vec3 (0, 0, 1)); + upDir = targetDir.cross (Vec3 (1, 0, 0)); + if (upDir.length() == 0) + upDir = targetDir.cross(Vec3 (0, 0, 1)); } // // Compute the x-, y-, and z-axis vectors of the new coordinate system. // - Vec3 targetPerpDir = upDir.cross (targetDir); + Vec3 targetPerpDir = upDir.cross (targetDir); Vec3 targetUpDir = targetDir.cross (targetPerpDir); - + // // Rotate the x-axis into targetPerpDir (row 0), // rotate the y-axis into targetUpDir (row 1), // rotate the z-axis into targetDir (row 2). // - + Vec3 row[3]; row[0] = targetPerpDir.normalized (); row[1] = targetUpDir .normalized (); row[2] = targetDir .normalized (); - + result.x[0][0] = row[0][0]; result.x[0][1] = row[0][1]; result.x[0][2] = row[0][2]; result.x[0][3] = (T)0; - + result.x[1][0] = row[1][0]; result.x[1][1] = row[1][1]; result.x[1][2] = row[1][2]; result.x[1][3] = (T)0; - + result.x[2][0] = row[2][0]; result.x[2][1] = row[2][1]; result.x[2][2] = row[2][2]; result.x[2][3] = (T)0; - + result.x[3][0] = (T)0; result.x[3][1] = (T)0; result.x[3][2] = (T)0; @@ -938,7 +928,7 @@ alignZAxisWithTargetDir (Matrix44 &result, Vec3 targetDir, Vec3 upDir) // Compute an orthonormal direct frame from : a position, an x axis direction and a normal to the y axis // If the x axis and normal are perpendicular, then the normal will have the same direction as the z axis. -// Inputs are : +// Inputs are : // -the position of the frame // -the x axis direction of the frame // -a normal to the y axis of the frame @@ -974,7 +964,7 @@ computeLocalFrame( const Vec3& p, L[3][1] = p[1]; L[3][2] = p[2]; L[3][3] = 1.0; - + return L; } @@ -1023,13 +1013,13 @@ addOffset( const Matrix44& inMat, template Matrix44 computeRSMatrix( bool keepRotateA, - bool keepScaleA, - const Matrix44& A, + bool keepScaleA, + const Matrix44& A, const Matrix44& B) { Vec3 as, ah, ar, at; extractSHRT (A, as, ah, ar, at); - + Vec3 bs, bh, br, bt; extractSHRT (B, bs, bh, br, bt); @@ -1044,7 +1034,7 @@ computeRSMatrix( bool keepRotateA, mat.translate (at); mat.rotate (ar); mat.scale (as); - + return mat; } @@ -1063,7 +1053,7 @@ extractScaling (const Matrix33 &mat, Vec2 &scl, bool exc) Matrix33 M (mat); if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) - return false; + return false; return true; } @@ -1079,10 +1069,10 @@ sansScaling (const Matrix33 &mat, bool exc) Vec2 tran; if (! extractSHRT (mat, scl, shr, rot, tran, exc)) - return mat; + return mat; Matrix33 M; - + M.translate (tran); M.rotate (rot); M.shear (shr); @@ -1101,7 +1091,7 @@ removeScaling (Matrix33 &mat, bool exc) Vec2 tran; if (! extractSHRT (mat, scl, shr, rot, tran, exc)) - return false; + return false; mat.makeIdentity (); mat.translate (tran); @@ -1119,7 +1109,7 @@ extractScalingAndShear (const Matrix33 &mat, Vec2 &scl, T &shr, bool exc) Matrix33 M (mat); if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) - return false; + return false; return true; } @@ -1134,8 +1124,8 @@ sansScalingAndShear (const Matrix33 &mat, bool exc) Matrix33 M (mat); if (! extractAndRemoveScalingAndShear (M, scl, shr, exc)) - return mat; - + return mat; + return M; } @@ -1148,55 +1138,55 @@ removeScalingAndShear (Matrix33 &mat, bool exc) T shr; if (! extractAndRemoveScalingAndShear (mat, scl, shr, exc)) - return false; - + return false; + return true; } template bool -extractAndRemoveScalingAndShear (Matrix33 &mat, - Vec2 &scl, T &shr, bool exc) +extractAndRemoveScalingAndShear (Matrix33 &mat, + Vec2 &scl, T &shr, bool exc) { Vec2 row[2]; row[0] = Vec2 (mat[0][0], mat[0][1]); row[1] = Vec2 (mat[1][0], mat[1][1]); - + T maxVal = 0; for (int i=0; i < 2; i++) - for (int j=0; j < 2; j++) - if (Imath::abs (row[i][j]) > maxVal) - maxVal = Imath::abs (row[i][j]); + for (int j=0; j < 2; j++) + if (IMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal) + maxVal = IMATH_INTERNAL_NAMESPACE::abs (row[i][j]); // // We normalize the 2x2 matrix here. // It was noticed that this can improve numerical stability significantly, // especially when many of the upper 2x2 matrix's coefficients are very - // close to zero; we correct for this step at the end by multiplying the - // scaling factors by maxVal at the end (shear and rotation are not + // close to zero; we correct for this step at the end by multiplying the + // scaling factors by maxVal at the end (shear and rotation are not // affected by the normalization). if (maxVal != 0) { - for (int i=0; i < 2; i++) - if (! checkForZeroScaleInRow (maxVal, row[i], exc)) - return false; - else - row[i] /= maxVal; + for (int i=0; i < 2; i++) + if (! checkForZeroScaleInRow (maxVal, row[i], exc)) + return false; + else + row[i] /= maxVal; } - // Compute X scale factor. + // Compute X scale factor. scl.x = row[0].length (); if (! checkForZeroScaleInRow (scl.x, row[0], exc)) - return false; + return false; // Normalize first row. row[0] /= scl.x; // An XY shear factor will shear the X coord. as the Y coord. changes. - // There are 2 combinations (XY, YX), although we only extract the XY - // shear factor because we can effect the an YX shear factor by + // There are 2 combinations (XY, YX), although we only extract the XY + // shear factor because we can effect the an YX shear factor by // shearing in XY combined with rotations and scales. // // shear matrix < 1, YX, 0, @@ -1210,30 +1200,30 @@ extractAndRemoveScalingAndShear (Matrix33 &mat, // Now, compute Y scale. scl.y = row[1].length (); if (! checkForZeroScaleInRow (scl.y, row[1], exc)) - return false; + return false; // Normalize 2nd row and correct the XY shear factor for Y scaling. - row[1] /= scl.y; + row[1] /= scl.y; shr /= scl.y; // At this point, the upper 2x2 matrix in mat is orthonormal. // Check for a coordinate system flip. If the determinant - // is -1, then flip the rotation matrix and adjust the scale(Y) + // is -1, then flip the rotation matrix and adjust the scale(Y) // and shear(XY) factors to compensate. if (row[0][0] * row[1][1] - row[0][1] * row[1][0] < 0) { - row[1][0] *= -1; - row[1][1] *= -1; - scl[1] *= -1; - shr *= -1; + row[1][0] *= -1; + row[1][1] *= -1; + scl[1] *= -1; + shr *= -1; } // Copy over the orthonormal rows into the returned matrix. // The upper 2x2 matrix in mat is now a rotation matrix. for (int i=0; i < 2; i++) { - mat[i][0] = row[i][0]; - mat[i][1] = row[i][1]; + mat[i][0] = row[i][0]; + mat[i][1] = row[i][1]; } scl *= maxVal; @@ -1258,26 +1248,26 @@ extractEuler (const Matrix33 &mat, T &rot) // // Extract the angle, rot. - // + // rot = - Math::atan2 (j[0], i[0]); } template -bool +bool extractSHRT (const Matrix33 &mat, - Vec2 &s, - T &h, - T &r, - Vec2 &t, - bool exc) + Vec2 &s, + T &h, + T &r, + Vec2 &t, + bool exc) { Matrix33 rot; rot = mat; if (! extractAndRemoveScalingAndShear (rot, s, h, exc)) - return false; + return false; extractEuler (rot, r); @@ -1288,22 +1278,22 @@ extractSHRT (const Matrix33 &mat, } -template -bool -checkForZeroScaleInRow (const T& scl, - const Vec2 &row, - bool exc /* = true */ ) +template +bool +checkForZeroScaleInRow (const T& scl, + const Vec2 &row, + bool exc /* = true */ ) { for (int i = 0; i < 2; i++) { - if ((abs (scl) < 1 && abs (row[i]) >= limits::max() * abs (scl))) - { - if (exc) - throw Imath::ZeroScaleExc ("Cannot remove zero scaling " - "from matrix."); - else - return false; - } + if ((abs (scl) < 1 && abs (row[i]) >= limits::max() * abs (scl))) + { + if (exc) + throw IMATH_INTERNAL_NAMESPACE::ZeroScaleExc ( + "Cannot remove zero scaling from matrix."); + else + return false; + } } return true; @@ -1321,7 +1311,7 @@ outerProduct (const Vec3 &a, const Vec3 &b ) // Computes the translation and rotation that brings the 'from' points -// as close as possible to the 'to' points under the Frobenius norm. +// as close as possible to the 'to' points under the Frobenius norm. // To be more specific, let x be the matrix of 'from' points and y be // the matrix of 'to' points, we want to find the matrix A of the form // [ R t ] @@ -1330,25 +1320,25 @@ outerProduct (const Vec3 &a, const Vec3 &b ) // || (A*x - y)^T * W * (A*x - y) ||_F // If doScaling is true, then a uniform scale is allowed also. template -Imath::M44d -procrustesRotationAndTranslation (const Imath::Vec3* A, // From these - const Imath::Vec3* B, // To these - const T* weights, +IMATH_INTERNAL_NAMESPACE::M44d +procrustesRotationAndTranslation (const IMATH_INTERNAL_NAMESPACE::Vec3* A, // From these + const IMATH_INTERNAL_NAMESPACE::Vec3* B, // To these + const T* weights, const size_t numPoints, const bool doScaling = false); // Unweighted: template -Imath::M44d -procrustesRotationAndTranslation (const Imath::Vec3* A, - const Imath::Vec3* B, +IMATH_INTERNAL_NAMESPACE::M44d +procrustesRotationAndTranslation (const IMATH_INTERNAL_NAMESPACE::Vec3* A, + const IMATH_INTERNAL_NAMESPACE::Vec3* B, const size_t numPoints, const bool doScaling = false); // Compute the SVD of a 3x3 matrix using Jacobi transformations. This method // should be quite accurate (competitive with LAPACK) even for poorly // conditioned matrices, and because it has been written specifically for the -// 3x3/4x4 case it is much faster than calling out to LAPACK. +// 3x3/4x4 case it is much faster than calling out to LAPACK. // // The SVD of a 3x3/4x4 matrix A is defined as follows: // A = U * S * V^T @@ -1357,25 +1347,25 @@ procrustesRotationAndTranslation (const Imath::Vec3* A, // the largest to the smallest. However, some uses of this function may // require that the matrix U*V^T have positive determinant; in this case, we // may make the smallest singular value negative to ensure that this is -// satisfied. +// satisfied. // // Currently only available for single- and double-precision matrices. template void -jacobiSVD (const Imath::Matrix33& A, - Imath::Matrix33& U, - Imath::Vec3& S, - Imath::Matrix33& V, - const T tol = Imath::limits::epsilon(), +jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix33& A, + IMATH_INTERNAL_NAMESPACE::Matrix33& U, + IMATH_INTERNAL_NAMESPACE::Vec3& S, + IMATH_INTERNAL_NAMESPACE::Matrix33& V, + const T tol = IMATH_INTERNAL_NAMESPACE::limits::epsilon(), const bool forcePositiveDeterminant = false); template void -jacobiSVD (const Imath::Matrix44& A, - Imath::Matrix44& U, - Imath::Vec4& S, - Imath::Matrix44& V, - const T tol = Imath::limits::epsilon(), +jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix44& A, + IMATH_INTERNAL_NAMESPACE::Matrix44& U, + IMATH_INTERNAL_NAMESPACE::Vec4& S, + IMATH_INTERNAL_NAMESPACE::Matrix44& V, + const T tol = IMATH_INTERNAL_NAMESPACE::limits::epsilon(), const bool forcePositiveDeterminant = false); // Compute the eigenvalues (S) and the eigenvectors (V) of @@ -1385,7 +1375,7 @@ jacobiSVD (const Imath::Matrix44& A, // A = V * S * V^T // where V is orthonormal and S is the diagonal matrix of eigenvalues. // Input matrix A must be symmetric. A is also modified during -// the computation so that upper diagonal entries of A become zero. +// the computation so that upper diagonal entries of A become zero. // template void @@ -1430,6 +1420,6 @@ template void minEigenVector (TM& A, TV& S); -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHMATRIXALGO_H diff --git a/3rdparty/openexr/Imath/ImathNamespace.h b/3rdparty/openexr/Imath/ImathNamespace.h new file mode 100644 index 0000000000..c1fb993529 --- /dev/null +++ b/3rdparty/openexr/Imath/ImathNamespace.h @@ -0,0 +1,115 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_IMATHNAMESPACE_H +#define INCLUDED_IMATHNAMESPACE_H + +// +// The purpose of this file is to make it possible to specify an +// IMATH_INTERNAL_NAMESPACE as a preprocessor definition and have all of the +// Imath symbols defined within that namespace rather than the standard +// Imath namespace. Those symbols are made available to client code through +// the IMATH_NAMESPACE in addition to the IMATH_INTERNAL_NAMESPACE. +// +// To ensure source code compatibility, the IMATH_NAMESPACE defaults to Imath +// and then "using namespace IMATH_INTERNAL_NAMESPACE;" brings all of the +// declarations from the IMATH_INTERNAL_NAMESPACE into the IMATH_NAMESPACE. +// This means that client code can continue to use syntax like Imath::V3f, +// but at link time it will resolve to a mangled symbol based on the +// IMATH_INTERNAL_NAMESPACE. +// +// As an example, if one needed to build against a newer version of Imath and +// have it run alongside an older version in the same application, it is now +// possible to use an internal namespace to prevent collisions between the +// older versions of Imath symbols and the newer ones. To do this, the +// following could be defined at build time: +// +// IMATH_INTERNAL_NAMESPACE = Imath_v2 +// +// This means that declarations inside Imath headers look like this (after +// the preprocessor has done its work): +// +// namespace Imath_v2 { +// ... +// class declarations +// ... +// } +// +// namespace Imath { +// using namespace Imath_v2; +// } +// + +// +// Open Source version of this file pulls in the IlmBaseConfig.h file +// for the configure time options. +// +#include "IlmBaseConfig.h" + + +#ifndef IMATH_NAMESPACE +#define IMATH_NAMESPACE Imath +#endif + +#ifndef IMATH_INTERNAL_NAMESPACE +#define IMATH_INTERNAL_NAMESPACE IMATH_NAMESPACE +#endif + +// +// We need to be sure that we import the internal namespace into the public one. +// To do this, we use the small bit of code below which initially defines +// IMATH_INTERNAL_NAMESPACE (so it can be referenced) and then defines +// IMATH_NAMESPACE and pulls the internal symbols into the public +// namespace. +// + +namespace IMATH_INTERNAL_NAMESPACE {} +namespace IMATH_NAMESPACE { + using namespace IMATH_INTERNAL_NAMESPACE; +} + +// +// There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that +// future extension to the namespace mechanism is possible without changing +// project source code. +// + +#define IMATH_INTERNAL_NAMESPACE_HEADER_ENTER namespace IMATH_INTERNAL_NAMESPACE { +#define IMATH_INTERNAL_NAMESPACE_HEADER_EXIT } + +#define IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER namespace IMATH_INTERNAL_NAMESPACE { +#define IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT } + + +#endif /* INCLUDED_IMATHNAMESPACE_H */ diff --git a/3rdparty/openexr/Imath/ImathPlane.h b/3rdparty/openexr/Imath/ImathPlane.h index b74195850a..7272d67ddf 100644 --- a/3rdparty/openexr/Imath/ImathPlane.h +++ b/3rdparty/openexr/Imath/ImathPlane.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -54,8 +54,9 @@ #include "ImathVec.h" #include "ImathLine.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template @@ -70,22 +71,22 @@ class Plane3 Plane3(const Vec3 &normal, T distance); Plane3(const Vec3 &point, const Vec3 &normal); Plane3(const Vec3 &point1, - const Vec3 &point2, - const Vec3 &point3); + const Vec3 &point2, + const Vec3 &point3); //---------------------- // Various set methods //---------------------- void set(const Vec3 &normal, - T distance); + T distance); void set(const Vec3 &point, - const Vec3 &normal); + const Vec3 &normal); void set(const Vec3 &point1, - const Vec3 &point2, - const Vec3 &point3 ); + const Vec3 &point2, + const Vec3 &point3 ); //---------------------- // Utilities @@ -95,7 +96,7 @@ class Plane3 Vec3 &intersection) const; bool intersectT(const Line3 &line, - T ¶meter) const; + T ¶meter) const; T distanceTo(const Vec3 &) const; @@ -118,8 +119,8 @@ typedef Plane3 Plane3d; template inline Plane3::Plane3(const Vec3 &p0, - const Vec3 &p1, - const Vec3 &p2) + const Vec3 &p1, + const Vec3 &p2) { set(p0,p1,p2); } @@ -138,8 +139,8 @@ inline Plane3::Plane3(const Vec3 &p, const Vec3 &n) template inline void Plane3::set(const Vec3& point1, - const Vec3& point2, - const Vec3& point3) + const Vec3& point2, + const Vec3& point3) { normal = (point2 - point1) % (point3 - point1); normal.normalize(); @@ -205,7 +206,7 @@ template std::ostream &operator<< (std::ostream &o, const Plane3 &plane) { return o << "(" << plane.normal << ", " << plane.distance - << ")"; + << ")"; } template @@ -224,8 +225,8 @@ Plane3 operator* (const Plane3 &plane, const Matrix44 &M) if (tmpLen > dir1Len) { - dir1 = tmp; - dir1Len = tmpLen; + dir1 = tmp; + dir1Len = tmpLen; } tmp = Vec3 (0, 0, 1) % plane.normal; @@ -233,15 +234,15 @@ Plane3 operator* (const Plane3 &plane, const Matrix44 &M) if (tmpLen > dir1Len) { - dir1 = tmp; + dir1 = tmp; } Vec3 dir2 = dir1 % plane.normal; Vec3 point = plane.distance * plane.normal; return Plane3 ( point * M, - (point + dir2) * M, - (point + dir1) * M ); + (point + dir2) * M, + (point + dir1) * M ); } template @@ -251,6 +252,6 @@ Plane3 operator- (const Plane3 &plane) } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHPLANE_H diff --git a/3rdparty/openexr/Imath/ImathPlatform.h b/3rdparty/openexr/Imath/ImathPlatform.h index 886b7709c1..91e82cc209 100644 --- a/3rdparty/openexr/Imath/ImathPlatform.h +++ b/3rdparty/openexr/Imath/ImathPlatform.h @@ -2,9 +2,9 @@ // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,8 +39,8 @@ // // ImathPlatform.h // -// This file contains functions and constants which aren't -// provided by the system libraries, compilers, or includes on +// This file contains functions and constants which aren't +// provided by the system libraries, compilers, or includes on // certain platforms. // //---------------------------------------------------------------------------- diff --git a/3rdparty/openexr/Imath/ImathQuat.h b/3rdparty/openexr/Imath/ImathQuat.h index 99c7d83011..e95e356d59 100644 --- a/3rdparty/openexr/Imath/ImathQuat.h +++ b/3rdparty/openexr/Imath/ImathQuat.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -57,10 +57,11 @@ #include "ImathExc.h" #include "ImathMatrix.h" +#include "ImathNamespace.h" #include -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // Disable MS VC++ warnings about conversion from double to float @@ -136,7 +137,7 @@ class Quat Quat & setAxisAngle (const Vec3 &axis, T radians); Quat & setRotation (const Vec3 &fromDirection, - const Vec3 &toDirection); + const Vec3 &toDirection); T angle () const; Vec3 axis () const; @@ -151,8 +152,8 @@ class Quat private: void setRotationInternal (const Vec3 &f0, - const Vec3 &t0, - Quat &q); + const Vec3 &t0, + Quat &q); }; @@ -165,13 +166,13 @@ Quat slerpShortestArc template -Quat squad (const Quat &q1, const Quat &q2, - const Quat &qa, const Quat &qb, T t); +Quat squad (const Quat &q1, const Quat &q2, + const Quat &qa, const Quat &qb, T t); template -void intermediate (const Quat &q0, const Quat &q1, - const Quat &q2, const Quat &q3, - Quat &qa, Quat &qb); +void intermediate (const Quat &q0, const Quat &q1, + const Quat &q2, const Quat &q3, + Quat &qa, Quat &qb); template Matrix33 operator * (const Matrix33 &M, const Quat &q); @@ -391,13 +392,13 @@ Quat::normalize () { if (T l = length()) { - r /= l; - v /= l; + r /= l; + v /= l; } else { - r = 1; - v = Vec3 (0); + r = 1; + v = Vec3 (0); } return *this; @@ -409,7 +410,7 @@ inline Quat Quat::normalized () const { if (T l = length()) - return Quat (r / l, v / l); + return Quat (r / l, v / l); return Quat(); } @@ -463,7 +464,7 @@ Quat::rotateVector(const Vec3& original) const template -inline T +inline T Quat::euclideanInnerProduct (const Quat &q) const { return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z; @@ -516,7 +517,7 @@ slerp (const Quat &q1, const Quat &q2, T t) T s = 1 - t; Quat q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 + - sinx_over_x (t * a) / sinx_over_x (a) * t * q2; + sinx_over_x (t * a) / sinx_over_x (a) * t * q2; return q.normalized(); } @@ -543,7 +544,7 @@ template Quat spline (const Quat &q0, const Quat &q1, const Quat &q2, const Quat &q3, - T t) + T t) { // // Spherical Cubic Spline Interpolation - @@ -555,17 +556,17 @@ spline (const Quat &q0, const Quat &q1, // Given a set of quaternion keys: q0, q1, q2, q3, // this routine does the interpolation between // q1 and q2 by constructing two intermediate - // quaternions: qa and qb. The qa and qb are - // computed by the intermediate function to + // quaternions: qa and qb. The qa and qb are + // computed by the intermediate function to // guarantee the continuity of tangents across // adjacent cubic segments. The qa represents in-tangent // for q1 and the qb represents the out-tangent for q2. - // - // The q1 q2 is the cubic segment being interpolated. - // The q0 is from the previous adjacent segment and q3 is + // + // The q1 q2 is the cubic segment being interpolated. + // The q0 is from the previous adjacent segment and q3 is // from the next adjacent segment. The q0 and q3 are used // in computing qa and qb. - // + // Quat qa = intermediate (q0, q1, q2); Quat qb = intermediate (q1, q2, q3); @@ -585,11 +586,11 @@ squad (const Quat &q1, const Quat &qa, // Spherical Quadrangle Interpolation - // from Advanced Animation and Rendering // Techniques by Watt and Watt, Page 366: - // It constructs a spherical cubic interpolation as - // a series of three spherical linear interpolations - // of a quadrangle of unit quaternions. - // - + // It constructs a spherical cubic interpolation as + // a series of three spherical linear interpolations + // of a quadrangle of unit quaternions. + // + Quat r1 = slerp (q1, q2, t); Quat r2 = slerp (qa, qb, t); Quat result = slerp (r1, r2, 2 * t * (1 - t)); @@ -605,10 +606,10 @@ intermediate (const Quat &q0, const Quat &q1, const Quat &q2) // // From advanced Animation and Rendering // Techniques by Watt and Watt, Page 366: - // computing the inner quadrangle + // computing the inner quadrangle // points (qa and qb) to guarantee tangent // continuity. - // + // Quat q1inv = q1.inverse(); Quat c1 = q1inv * q2; @@ -625,22 +626,22 @@ inline Quat Quat::log () const { // - // For unit quaternion, from Advanced Animation and + // For unit quaternion, from Advanced Animation and // Rendering Techniques by Watt and Watt, Page 366: // T theta = Math::acos (std::min (r, (T) 1.0)); if (theta == 0) - return Quat (0, v); - + return Quat (0, v); + T sintheta = Math::sin (theta); - + T k; if (abs (sintheta) < 1 && abs (theta) >= limits::max() * abs (sintheta)) - k = 1; + k = 1; else - k = theta / sintheta; + k = theta / sintheta; return Quat ((T) 0, v.x * k, v.y * k, v.z * k); } @@ -658,12 +659,12 @@ Quat::exp () const T theta = v.length(); T sintheta = Math::sin (theta); - + T k; if (abs (theta) < 1 && abs (sintheta) >= limits::max() * abs (theta)) - k = 1; + k = 1; else - k = sintheta / theta; + k = sintheta / theta; T costheta = Math::cos (theta); @@ -722,50 +723,50 @@ Quat::setRotation (const Vec3 &from, const Vec3 &to) if ((f0 ^ t0) >= 0) { - // - // The rotation angle is less than or equal to pi/2. - // + // + // The rotation angle is less than or equal to pi/2. + // - setRotationInternal (f0, t0, *this); + setRotationInternal (f0, t0, *this); } else { - // - // The angle is greater than pi/2. After computing h0, - // which is halfway between f0 and t0, we rotate first - // from f0 to h0, then from h0 to t0. - // - - Vec3 h0 = (f0 + t0).normalized(); - - if ((h0 ^ h0) != 0) - { - setRotationInternal (f0, h0, *this); - - Quat q; - setRotationInternal (h0, t0, q); - - *this *= q; - } - else - { - // - // f0 and t0 point in exactly opposite directions. - // Pick an arbitrary axis that is orthogonal to f0, - // and rotate by pi. - // - - r = T (0); - - Vec3 f02 = f0 * f0; - - if (f02.x <= f02.y && f02.x <= f02.z) - v = (f0 % Vec3 (1, 0, 0)).normalized(); - else if (f02.y <= f02.z) - v = (f0 % Vec3 (0, 1, 0)).normalized(); - else - v = (f0 % Vec3 (0, 0, 1)).normalized(); - } + // + // The angle is greater than pi/2. After computing h0, + // which is halfway between f0 and t0, we rotate first + // from f0 to h0, then from h0 to t0. + // + + Vec3 h0 = (f0 + t0).normalized(); + + if ((h0 ^ h0) != 0) + { + setRotationInternal (f0, h0, *this); + + Quat q; + setRotationInternal (h0, t0, q); + + *this *= q; + } + else + { + // + // f0 and t0 point in exactly opposite directions. + // Pick an arbitrary axis that is orthogonal to f0, + // and rotate by pi. + // + + r = T (0); + + Vec3 f02 = f0 * f0; + + if (f02.x <= f02.y && f02.x <= f02.z) + v = (f0 % Vec3 (1, 0, 0)).normalized(); + else if (f02.y <= f02.z) + v = (f0 % Vec3 (0, 1, 0)).normalized(); + else + v = (f0 % Vec3 (0, 0, 1)).normalized(); + } } return *this; @@ -809,16 +810,16 @@ Matrix33 Quat::toMatrix33() const { return Matrix33 (1 - 2 * (v.y * v.y + v.z * v.z), - 2 * (v.x * v.y + v.z * r), - 2 * (v.z * v.x - v.y * r), + 2 * (v.x * v.y + v.z * r), + 2 * (v.z * v.x - v.y * r), - 2 * (v.x * v.y - v.z * r), - 1 - 2 * (v.z * v.z + v.x * v.x), - 2 * (v.y * v.z + v.x * r), + 2 * (v.x * v.y - v.z * r), + 1 - 2 * (v.z * v.z + v.x * v.x), + 2 * (v.y * v.z + v.x * r), - 2 * (v.z * v.x + v.y * r), - 2 * (v.y * v.z - v.x * r), - 1 - 2 * (v.y * v.y + v.x * v.x)); + 2 * (v.z * v.x + v.y * r), + 2 * (v.y * v.z - v.x * r), + 1 - 2 * (v.y * v.y + v.x * v.x)); } template @@ -826,21 +827,21 @@ Matrix44 Quat::toMatrix44() const { return Matrix44 (1 - 2 * (v.y * v.y + v.z * v.z), - 2 * (v.x * v.y + v.z * r), - 2 * (v.z * v.x - v.y * r), - 0, - 2 * (v.x * v.y - v.z * r), - 1 - 2 * (v.z * v.z + v.x * v.x), - 2 * (v.y * v.z + v.x * r), - 0, - 2 * (v.z * v.x + v.y * r), - 2 * (v.y * v.z - v.x * r), - 1 - 2 * (v.y * v.y + v.x * v.x), - 0, - 0, - 0, - 0, - 1); + 2 * (v.x * v.y + v.z * r), + 2 * (v.z * v.x - v.y * r), + 0, + 2 * (v.x * v.y - v.z * r), + 1 - 2 * (v.z * v.z + v.x * v.x), + 2 * (v.y * v.z + v.x * r), + 0, + 2 * (v.z * v.x + v.y * r), + 2 * (v.y * v.z - v.x * r), + 1 - 2 * (v.y * v.y + v.x * v.x), + 0, + 0, + 0, + 0, + 1); } @@ -865,10 +866,10 @@ std::ostream & operator << (std::ostream &o, const Quat &q) { return o << "(" << q.r - << " " << q.v.x - << " " << q.v.y - << " " << q.v.z - << ")"; + << " " << q.v.x + << " " << q.v.y + << " " << q.v.z + << ")"; } @@ -877,7 +878,7 @@ inline Quat operator * (const Quat &q1, const Quat &q2) { return Quat (q1.r * q2.r - (q1.v ^ q2.v), - q1.r * q2.v + q1.v * q2.r + q1.v % q2.v); + q1.r * q2.v + q1.v * q2.r + q1.v % q2.v); } @@ -958,6 +959,6 @@ operator * (const Vec3 &v, const Quat &q) #pragma warning(default:4244) #endif -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHQUAT_H diff --git a/3rdparty/openexr/Imath/ImathRandom.cpp b/3rdparty/openexr/Imath/ImathRandom.cpp index 23a0e17d40..cf3d600415 100644 --- a/3rdparty/openexr/Imath/ImathRandom.cpp +++ b/3rdparty/openexr/Imath/ImathRandom.cpp @@ -1,11 +1,10 @@ - /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -17,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,7 +42,7 @@ #include "ImathRandom.h" #include "ImathInt64.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER namespace { // @@ -61,7 +60,7 @@ rand48Next (unsigned short state[3]) // sequence, // // x[n+1] = (a * x[n] + c) % m, - // + // // where a and c are as specified below, and m == (1 << 48) // @@ -74,8 +73,8 @@ rand48Next (unsigned short state[3]) // Int64 x = (Int64 (state[2]) << 32) | - (Int64 (state[1]) << 16) | - Int64 (state[0]); + (Int64 (state[1]) << 16) | + Int64 (state[0]); // // Compute x[n+1], except for the "modulo m" part. @@ -104,7 +103,7 @@ erand48 (unsigned short state[3]) { // // Generate double-precision floating-point values between 0.0 and 1.0: - // + // // The exponent is set to 0x3ff, which indicates a value greater // than or equal to 1.0, and less than 2.0. The 48 most significant // bits of the significand (mantissa) are filled with pseudo-random @@ -115,17 +114,17 @@ erand48 (unsigned short state[3]) // between 1.0 and 1.99999999999999978. Subtracting 1.0 from those // values produces numbers between 0.0 and 0.99999999999999978, that // is, between 0.0 and 1.0-DBL_EPSILON. - // + // rand48Next (state); union {double d; Int64 i;} u; u.i = (Int64 (0x3ff) << 52) | // sign and exponent - (Int64 (state[2]) << 36) | // significand - (Int64 (state[1]) << 20) | - (Int64 (state[0]) << 4) | - (Int64 (state[2]) >> 12); + (Int64 (state[2]) << 36) | // significand + (Int64 (state[1]) << 20) | + (Int64 (state[0]) << 4) | + (Int64 (state[2]) >> 12); return u.d - 1; } @@ -134,7 +133,7 @@ erand48 (unsigned short state[3]) double drand48 () { - return Imath::erand48 (staticState); + return IMATH_INTERNAL_NAMESPACE::erand48 (staticState); } @@ -143,19 +142,19 @@ nrand48 (unsigned short state[3]) { // // Generate uniformly distributed integers between 0 and 0x7fffffff. - // + // rand48Next (state); return ((long int) (state[2]) << 15) | - ((long int) (state[1]) >> 1); + ((long int) (state[1]) >> 1); } long int lrand48 () { - return Imath::nrand48 (staticState); + return IMATH_INTERNAL_NAMESPACE::nrand48 (staticState); } @@ -173,7 +172,7 @@ Rand32::nextf () { // // Generate single-precision floating-point values between 0.0 and 1.0: - // + // // The exponent is set to 0x7f, which indicates a value greater than // or equal to 1.0, and less than 2.0. The 23 bits of the significand // (mantissa) are filled with pseudo-random bits generated by @@ -182,7 +181,7 @@ Rand32::nextf () // point values between 1.0 and 1.99999988. Subtracting 1.0 from // those values produces numbers between 0.0 and 0.99999988, that is, // between 0.0 and 1.0-FLT_EPSILON. - // + // next (); @@ -192,4 +191,4 @@ Rand32::nextf () return u.f - 1; } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/Imath/ImathRandom.h b/3rdparty/openexr/Imath/ImathRandom.h index 8a4dc149c9..4f0db1312f 100644 --- a/3rdparty/openexr/Imath/ImathRandom.h +++ b/3rdparty/openexr/Imath/ImathRandom.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -56,10 +56,13 @@ // //----------------------------------------------------------------------------- +#include "ImathNamespace.h" +#include "ImathExport.h" + #include #include -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER //----------------------------------------------- // Fast random-number generator that generates @@ -67,7 +70,7 @@ namespace Imath { // length of 2^32. //----------------------------------------------- -class Rand32 +class IMATH_EXPORT Rand32 { public: @@ -76,7 +79,7 @@ class Rand32 //------------ Rand32 (unsigned long int seed = 0); - + //-------------------------------- // Re-initialize with a given seed @@ -136,7 +139,7 @@ class Rand48 //------------ Rand48 (unsigned long int seed = 0); - + //-------------------------------- // Re-initialize with a given seed @@ -185,7 +188,7 @@ class Rand48 //------------------------------------------------------------ template -Vec +Vec solidSphereRand (Rand &rand); @@ -195,7 +198,7 @@ solidSphereRand (Rand &rand); //------------------------------------------------------------- template -Vec +Vec hollowSphereRand (Rand &rand); @@ -224,11 +227,11 @@ gaussSphereRand (Rand &rand); // erand48(), nrand48() and friends //--------------------------------- -double erand48 (unsigned short state[3]); -double drand48 (); -long int nrand48 (unsigned short state[3]); -long int lrand48 (); -void srand48 (long int seed); +IMATH_EXPORT double erand48 (unsigned short state[3]); +IMATH_EXPORT double drand48 (); +IMATH_EXPORT long int nrand48 (unsigned short state[3]); +IMATH_EXPORT long int lrand48 (); +IMATH_EXPORT void srand48 (long int seed); //--------------- @@ -289,11 +292,11 @@ Rand48::init (unsigned long int seed) _state[0] = (unsigned short int) (seed & 0xFFFF); _state[1] = (unsigned short int) ((seed >> 16) & 0xFFFF); - _state[2] = (unsigned short int) (seed & 0xFFFF); + _state[2] = (unsigned short int) (seed & 0xFFFF); } -inline +inline Rand48::Rand48 (unsigned long int seed) { init (seed); @@ -303,21 +306,21 @@ Rand48::Rand48 (unsigned long int seed) inline bool Rand48::nextb () { - return Imath::nrand48 (_state) & 1; + return nrand48 (_state) & 1; } inline long int Rand48::nexti () { - return Imath::nrand48 (_state); + return nrand48 (_state); } inline double Rand48::nextf () { - return Imath::erand48 (_state); + return erand48 (_state); } @@ -337,8 +340,8 @@ solidSphereRand (Rand &rand) do { - for (unsigned int i = 0; i < Vec::dimensions(); i++) - v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); + for (unsigned int i = 0; i < Vec::dimensions(); i++) + v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); } while (v.length2() > 1); @@ -355,10 +358,10 @@ hollowSphereRand (Rand &rand) do { - for (unsigned int i = 0; i < Vec::dimensions(); i++) - v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); + for (unsigned int i = 0; i < Vec::dimensions(); i++) + v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); - length = v.length(); + length = v.length(); } while (length > 1 || length == 0); @@ -373,12 +376,12 @@ gaussRand (Rand &rand) float x; // Note: to avoid numerical problems with very small float y; // numbers, we make these variables singe-precision float length2; // floats, but later we call the double-precision log() - // and sqrt() functions instead of logf() and sqrtf(). + // and sqrt() functions instead of logf() and sqrtf(). do { - x = float (rand.nextf (-1, 1)); - y = float (rand.nextf (-1, 1)); - length2 = x * x + y * y; + x = float (rand.nextf (-1, 1)); + y = float (rand.nextf (-1, 1)); + length2 = x * x + y * y; } while (length2 >= 1 || length2 == 0); @@ -393,6 +396,6 @@ gaussSphereRand (Rand &rand) return hollowSphereRand (rand) * gaussRand (rand); } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHRANDOM_H diff --git a/3rdparty/openexr/Imath/ImathRoots.h b/3rdparty/openexr/Imath/ImathRoots.h index df3f3904d0..036b7f7468 100644 --- a/3rdparty/openexr/Imath/ImathRoots.h +++ b/3rdparty/openexr/Imath/ImathRoots.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,10 +43,11 @@ // //--------------------------------------------------------------------- -#include +#include "ImathMath.h" +#include "ImathNamespace.h" #include -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER //-------------------------------------------------------------------------- // Find the real solutions of a linear, quadratic or cubic equation: @@ -97,16 +98,16 @@ solveLinear (T a, T b, T &x) { if (a != 0) { - x = -b / a; - return 1; + x = -b / a; + return 1; } else if (b != 0) { - return 0; + return 0; } else { - return -1; + return -1; } } @@ -117,30 +118,30 @@ solveQuadratic (T a, T b, T c, T x[2]) { if (a == 0) { - return solveLinear (b, c, x[0]); - } - else - { - T D = b * b - 4 * a * c; - - if (D > 0) - { - T s = Math::sqrt (D); - T q = -(b + (b > 0 ? 1 : -1) * s) / T(2); - - x[0] = q / a; - x[1] = c / q; - return 2; - } - if (D == 0) - { - x[0] = -b / (2 * a); - return 1; + return solveLinear (b, c, x[0]); } else { - return 0; - } + T D = b * b - 4 * a * c; + + if (D > 0) + { + T s = Math::sqrt (D); + T q = -(b + (b > 0 ? 1 : -1) * s) / T(2); + + x[0] = q / a; + x[1] = c / q; + return 2; + } + if (D == 0) + { + x[0] = -b / (2 * a); + return 1; + } + else + { + return 0; + } } } @@ -157,44 +158,44 @@ solveNormalizedCubic (T r, T s, T t, T x[3]) if (D == 0 && p3 == 0) { - x[0] = -r / 3; - x[1] = -r / 3; - x[2] = -r / 3; - return 1; + x[0] = -r / 3; + x[1] = -r / 3; + x[2] = -r / 3; + return 1; } std::complex u = std::pow (-q / 2 + std::sqrt (std::complex (D)), - T (1) / T (3)); + T (1) / T (3)); std::complex v = -p / (T (3) * u); const T sqrt3 = T (1.73205080756887729352744634150587); // enough digits - // for long double + // for long double std::complex y0 (u + v); std::complex y1 (-(u + v) / T (2) + - (u - v) / T (2) * std::complex (0, sqrt3)); + (u - v) / T (2) * std::complex (0, sqrt3)); std::complex y2 (-(u + v) / T (2) - - (u - v) / T (2) * std::complex (0, sqrt3)); + (u - v) / T (2) * std::complex (0, sqrt3)); if (D > 0) { - x[0] = y0.real() - r / 3; - return 1; + x[0] = y0.real() - r / 3; + return 1; } else if (D == 0) { - x[0] = y0.real() - r / 3; - x[1] = y1.real() - r / 3; - return 2; + x[0] = y0.real() - r / 3; + x[1] = y1.real() - r / 3; + return 2; } else { - x[0] = y0.real() - r / 3; - x[1] = y1.real() - r / 3; - x[2] = y2.real() - r / 3; - return 3; + x[0] = y0.real() - r / 3; + x[1] = y1.real() - r / 3; + x[2] = y2.real() - r / 3; + return 3; } } @@ -205,15 +206,14 @@ solveCubic (T a, T b, T c, T d, T x[3]) { if (a == 0) { - return solveQuadratic (b, c, d, x); + return solveQuadratic (b, c, d, x); } else { - return solveNormalizedCubic (b / a, c / a, d / a, x); + return solveNormalizedCubic (b / a, c / a, d / a, x); } } +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -} // namespace Imath - -#endif +#endif // INCLUDED_IMATHROOTS_H diff --git a/3rdparty/openexr/Imath/ImathShear.cpp b/3rdparty/openexr/Imath/ImathShear.cpp new file mode 100644 index 0000000000..2c0ba2ae1b --- /dev/null +++ b/3rdparty/openexr/Imath/ImathShear.cpp @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas +// Digital Ltd. LLC +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Industrial Light & Magic nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////// + + + + +//---------------------------------------------------------------------------- +// +// Specializations of the Shear6 template. +// +//---------------------------------------------------------------------------- + +#include "ImathShear.h" + +IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER + + + +// empty + + + +IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/Imath/ImathShear.h b/3rdparty/openexr/Imath/ImathShear.h index 132ab1eb9e..b6f7b9a968 100644 --- a/3rdparty/openexr/Imath/ImathShear.h +++ b/3rdparty/openexr/Imath/ImathShear.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -47,14 +47,11 @@ #include "ImathLimits.h" #include "ImathMath.h" #include "ImathVec.h" - +#include "ImathNamespace.h" #include -namespace Imath { - - - +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template class Shear6 { @@ -78,9 +75,9 @@ template class Shear6 Shear6 (T XY, T XZ, T YZ); // (XY XZ YZ 0 0 0) Shear6 (const Vec3 &v); // (v.x v.y v.z 0 0 0) template // (v.x v.y v.z 0 0 0) - Shear6 (const Vec3 &v); + Shear6 (const Vec3 &v); Shear6 (T XY, T XZ, T YZ, // (XY XZ YZ YX ZX ZY) - T YX, T ZX, T ZY); + T YX, T ZX, T ZY); //--------------------------------- @@ -91,8 +88,8 @@ template class Shear6 template Shear6 (const Shear6 &h); const Shear6 & operator = (const Shear6 &h); - template - const Shear6 & operator = (const Vec3 &v); + template + const Shear6 & operator = (const Vec3 &v); //---------------------- @@ -106,8 +103,8 @@ template class Shear6 void setValue (const Shear6 &h); template - void getValue (S &XY, S &XZ, S &YZ, - S &YX, S &ZX, S &ZY) const; + void getValue (S &XY, S &XZ, S &YZ, + S &YX, S &ZX, S &ZY) const; template void getValue (Shear6 &h) const; @@ -443,8 +440,8 @@ template inline bool Shear6::operator == (const Shear6 &h) const { - return xy == h.xy && xz == h.xz && yz == h.yz && - yx == h.yx && zx == h.zx && zy == h.zy; + return xy == h.xy && xz == h.xz && yz == h.yz && + yx == h.yx && zx == h.zx && zy == h.zy; } template @@ -453,7 +450,7 @@ inline bool Shear6::operator != (const Shear6 &h) const { return xy != h.xy || xz != h.xz || yz != h.yz || - yx != h.yx || zx != h.zx || zy != h.zy; + yx != h.yx || zx != h.zx || zy != h.zy; } template @@ -461,8 +458,8 @@ bool Shear6::equalWithAbsError (const Shear6 &h, T e) const { for (int i = 0; i < 6; i++) - if (!Imath::equalWithAbsError ((*this)[i], h[i], e)) - return false; + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], h[i], e)) + return false; return true; } @@ -472,8 +469,8 @@ bool Shear6::equalWithRelError (const Shear6 &h, T e) const { for (int i = 0; i < 6; i++) - if (!Imath::equalWithRelError ((*this)[i], h[i], e)) - return false; + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], h[i], e)) + return false; return true; } @@ -497,7 +494,7 @@ inline Shear6 Shear6::operator + (const Shear6 &h) const { return Shear6 (xy + h.xy, xz + h.xz, yz + h.yz, - yx + h.yx, zx + h.zx, zy + h.zy); + yx + h.yx, zx + h.zx, zy + h.zy); } template @@ -518,7 +515,7 @@ inline Shear6 Shear6::operator - (const Shear6 &h) const { return Shear6 (xy - h.xy, xz - h.xz, yz - h.yz, - yx - h.yx, zx - h.zx, zy - h.zy); + yx - h.yx, zx - h.zx, zy - h.zy); } template @@ -571,8 +568,8 @@ template inline Shear6 Shear6::operator * (const Shear6 &h) const { - return Shear6 (xy * h.xy, xz * h.xz, yz * h.yz, - yx * h.yx, zx * h.zx, zy * h.zy); + return Shear6 (xy * h.xy, xz * h.xz, yz * h.yz, + yx * h.yx, zx * h.zx, zy * h.zy); } template @@ -580,7 +577,7 @@ inline Shear6 Shear6::operator * (T a) const { return Shear6 (xy * a, xz * a, yz * a, - yx * a, zx * a, zy * a); + yx * a, zx * a, zy * a); } template @@ -614,7 +611,7 @@ inline Shear6 Shear6::operator / (const Shear6 &h) const { return Shear6 (xy / h.xy, xz / h.xz, yz / h.yz, - yx / h.yx, zx / h.zx, zy / h.zy); + yx / h.yx, zx / h.zx, zy / h.zy); } template @@ -622,7 +619,7 @@ inline Shear6 Shear6::operator / (T a) const { return Shear6 (xy / a, xz / a, yz / a, - yx / a, zx / a, zy / a); + yx / a, zx / a, zy / a); } @@ -634,10 +631,10 @@ template std::ostream & operator << (std::ostream &s, const Shear6 &h) { - return s << '(' - << h.xy << ' ' << h.xz << ' ' << h.yz - << h.yx << ' ' << h.zx << ' ' << h.zy - << ')'; + return s << '(' + << h.xy << ' ' << h.xz << ' ' << h.yz + << h.yx << ' ' << h.zx << ' ' << h.zy + << ')'; } @@ -650,10 +647,10 @@ inline Shear6 operator * (S a, const Shear6 &h) { return Shear6 (a * h.xy, a * h.xz, a * h.yz, - a * h.yx, a * h.zx, a * h.zy); + a * h.yx, a * h.zx, a * h.zy); } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHSHEAR_H diff --git a/3rdparty/openexr/Imath/ImathSphere.h b/3rdparty/openexr/Imath/ImathSphere.h index 83645eb9bd..e8f36dfe56 100644 --- a/3rdparty/openexr/Imath/ImathSphere.h +++ b/3rdparty/openexr/Imath/ImathSphere.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,8 +46,9 @@ #include "ImathVec.h" #include "ImathBox.h" #include "ImathLine.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template class Sphere3 @@ -129,26 +130,26 @@ bool Sphere3::intersectT(const Line3 &line, T &t) const if (discr < 0.0) { - // line and Sphere3 do not intersect + // line and Sphere3 do not intersect - doesIntersect = false; + doesIntersect = false; } else { - // t0: (-B - sqrt(B^2 - 4AC)) / 2A (A = 1) + // t0: (-B - sqrt(B^2 - 4AC)) / 2A (A = 1) - T sqroot = Math::sqrt(discr); - t = (-B - sqroot) * T(0.5); + T sqroot = Math::sqrt(discr); + t = (-B - sqroot) * T(0.5); - if (t < 0.0) - { - // no intersection, try t1: (-B + sqrt(B^2 - 4AC)) / 2A (A = 1) + if (t < 0.0) + { + // no intersection, try t1: (-B + sqrt(B^2 - 4AC)) / 2A (A = 1) - t = (-B + sqroot) * T(0.5); - } + t = (-B + sqroot) * T(0.5); + } - if (t < 0.0) - doesIntersect = false; + if (t < 0.0) + doesIntersect = false; } return doesIntersect; @@ -162,16 +163,15 @@ bool Sphere3::intersect(const Line3 &line, Vec3 &intersection) const if (intersectT (line, t)) { - intersection = line(t); - return true; + intersection = line(t); + return true; } else { - return false; + return false; } } +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -} //namespace Imath - -#endif +#endif // INCLUDED_IMATHSPHERE_H diff --git a/3rdparty/openexr/Imath/ImathVec.cpp b/3rdparty/openexr/Imath/ImathVec.cpp index a853e0c7cd..37edc970ce 100644 --- a/3rdparty/openexr/Imath/ImathVec.cpp +++ b/3rdparty/openexr/Imath/ImathVec.cpp @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -41,6 +41,7 @@ //---------------------------------------------------------------------------- #include "ImathVec.h" +#include "ImathExport.h" #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // suppress exception specification warnings @@ -48,7 +49,7 @@ #endif -namespace Imath { +IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER namespace { @@ -126,7 +127,8 @@ normalizeOrThrow(Vec4 &v) // Vec2 -template <> +template <> +IMATH_EXPORT short Vec2::length () const { @@ -136,6 +138,7 @@ Vec2::length () const } template <> +IMATH_EXPORT const Vec2 & Vec2::normalize () { @@ -144,8 +147,9 @@ Vec2::normalize () } template <> +IMATH_EXPORT const Vec2 & -Vec2::normalizeExc () throw (Iex::MathExc) +Vec2::normalizeExc () { if ((x == 0) && (y == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -155,6 +159,7 @@ Vec2::normalizeExc () throw (Iex::MathExc) } template <> +IMATH_EXPORT const Vec2 & Vec2::normalizeNonNull () { @@ -163,6 +168,7 @@ Vec2::normalizeNonNull () } template <> +IMATH_EXPORT Vec2 Vec2::normalized () const { @@ -172,8 +178,9 @@ Vec2::normalized () const } template <> +IMATH_EXPORT Vec2 -Vec2::normalizedExc () const throw (Iex::MathExc) +Vec2::normalizedExc () const { if ((x == 0) && (y == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -184,6 +191,7 @@ Vec2::normalizedExc () const throw (Iex::MathExc) } template <> +IMATH_EXPORT Vec2 Vec2::normalizedNonNull () const { @@ -195,7 +203,8 @@ Vec2::normalizedNonNull () const // Vec2 -template <> +template <> +IMATH_EXPORT int Vec2::length () const { @@ -205,6 +214,7 @@ Vec2::length () const } template <> +IMATH_EXPORT const Vec2 & Vec2::normalize () { @@ -213,8 +223,9 @@ Vec2::normalize () } template <> +IMATH_EXPORT const Vec2 & -Vec2::normalizeExc () throw (Iex::MathExc) +Vec2::normalizeExc () { if ((x == 0) && (y == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -224,6 +235,7 @@ Vec2::normalizeExc () throw (Iex::MathExc) } template <> +IMATH_EXPORT const Vec2 & Vec2::normalizeNonNull () { @@ -232,6 +244,7 @@ Vec2::normalizeNonNull () } template <> +IMATH_EXPORT Vec2 Vec2::normalized () const { @@ -241,8 +254,9 @@ Vec2::normalized () const } template <> +IMATH_EXPORT Vec2 -Vec2::normalizedExc () const throw (Iex::MathExc) +Vec2::normalizedExc () const { if ((x == 0) && (y == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -253,6 +267,7 @@ Vec2::normalizedExc () const throw (Iex::MathExc) } template <> +IMATH_EXPORT Vec2 Vec2::normalizedNonNull () const { @@ -264,7 +279,8 @@ Vec2::normalizedNonNull () const // Vec3 -template <> +template <> +IMATH_EXPORT short Vec3::length () const { @@ -274,6 +290,7 @@ Vec3::length () const } template <> +IMATH_EXPORT const Vec3 & Vec3::normalize () { @@ -282,8 +299,9 @@ Vec3::normalize () } template <> +IMATH_EXPORT const Vec3 & -Vec3::normalizeExc () throw (Iex::MathExc) +Vec3::normalizeExc () { if ((x == 0) && (y == 0) && (z == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -293,6 +311,7 @@ Vec3::normalizeExc () throw (Iex::MathExc) } template <> +IMATH_EXPORT const Vec3 & Vec3::normalizeNonNull () { @@ -301,6 +320,7 @@ Vec3::normalizeNonNull () } template <> +IMATH_EXPORT Vec3 Vec3::normalized () const { @@ -310,8 +330,9 @@ Vec3::normalized () const } template <> +IMATH_EXPORT Vec3 -Vec3::normalizedExc () const throw (Iex::MathExc) +Vec3::normalizedExc () const { if ((x == 0) && (y == 0) && (z == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -322,6 +343,7 @@ Vec3::normalizedExc () const throw (Iex::MathExc) } template <> +IMATH_EXPORT Vec3 Vec3::normalizedNonNull () const { @@ -333,7 +355,8 @@ Vec3::normalizedNonNull () const // Vec3 -template <> +template <> +IMATH_EXPORT int Vec3::length () const { @@ -343,6 +366,7 @@ Vec3::length () const } template <> +IMATH_EXPORT const Vec3 & Vec3::normalize () { @@ -351,8 +375,9 @@ Vec3::normalize () } template <> +IMATH_EXPORT const Vec3 & -Vec3::normalizeExc () throw (Iex::MathExc) +Vec3::normalizeExc () { if ((x == 0) && (y == 0) && (z == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -362,6 +387,7 @@ Vec3::normalizeExc () throw (Iex::MathExc) } template <> +IMATH_EXPORT const Vec3 & Vec3::normalizeNonNull () { @@ -370,6 +396,7 @@ Vec3::normalizeNonNull () } template <> +IMATH_EXPORT Vec3 Vec3::normalized () const { @@ -379,8 +406,9 @@ Vec3::normalized () const } template <> +IMATH_EXPORT Vec3 -Vec3::normalizedExc () const throw (Iex::MathExc) +Vec3::normalizedExc () const { if ((x == 0) && (y == 0) && (z == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -391,6 +419,7 @@ Vec3::normalizedExc () const throw (Iex::MathExc) } template <> +IMATH_EXPORT Vec3 Vec3::normalizedNonNull () const { @@ -402,7 +431,8 @@ Vec3::normalizedNonNull () const // Vec4 -template <> +template <> +IMATH_EXPORT short Vec4::length () const { @@ -412,6 +442,7 @@ Vec4::length () const } template <> +IMATH_EXPORT const Vec4 & Vec4::normalize () { @@ -420,8 +451,9 @@ Vec4::normalize () } template <> +IMATH_EXPORT const Vec4 & -Vec4::normalizeExc () throw (Iex::MathExc) +Vec4::normalizeExc () { if ((x == 0) && (y == 0) && (z == 0) && (w == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -431,6 +463,7 @@ Vec4::normalizeExc () throw (Iex::MathExc) } template <> +IMATH_EXPORT const Vec4 & Vec4::normalizeNonNull () { @@ -439,6 +472,7 @@ Vec4::normalizeNonNull () } template <> +IMATH_EXPORT Vec4 Vec4::normalized () const { @@ -448,8 +482,9 @@ Vec4::normalized () const } template <> +IMATH_EXPORT Vec4 -Vec4::normalizedExc () const throw (Iex::MathExc) +Vec4::normalizedExc () const { if ((x == 0) && (y == 0) && (z == 0) && (w == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -460,6 +495,7 @@ Vec4::normalizedExc () const throw (Iex::MathExc) } template <> +IMATH_EXPORT Vec4 Vec4::normalizedNonNull () const { @@ -471,7 +507,8 @@ Vec4::normalizedNonNull () const // Vec4 -template <> +template <> +IMATH_EXPORT int Vec4::length () const { @@ -481,6 +518,7 @@ Vec4::length () const } template <> +IMATH_EXPORT const Vec4 & Vec4::normalize () { @@ -489,8 +527,9 @@ Vec4::normalize () } template <> +IMATH_EXPORT const Vec4 & -Vec4::normalizeExc () throw (Iex::MathExc) +Vec4::normalizeExc () { if ((x == 0) && (y == 0) && (z == 0) && (w == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -500,6 +539,7 @@ Vec4::normalizeExc () throw (Iex::MathExc) } template <> +IMATH_EXPORT const Vec4 & Vec4::normalizeNonNull () { @@ -508,6 +548,7 @@ Vec4::normalizeNonNull () } template <> +IMATH_EXPORT Vec4 Vec4::normalized () const { @@ -517,8 +558,9 @@ Vec4::normalized () const } template <> +IMATH_EXPORT Vec4 -Vec4::normalizedExc () const throw (Iex::MathExc) +Vec4::normalizedExc () const { if ((x == 0) && (y == 0) && (z == 0) && (w == 0)) throw NullVecExc ("Cannot normalize null vector."); @@ -529,6 +571,7 @@ Vec4::normalizedExc () const throw (Iex::MathExc) } template <> +IMATH_EXPORT Vec4 Vec4::normalizedNonNull () const { @@ -537,4 +580,4 @@ Vec4::normalizedNonNull () const return v; } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/3rdparty/openexr/Imath/ImathVec.h b/3rdparty/openexr/Imath/ImathVec.h index d8c044ffef..6f4e82a38e 100644 --- a/3rdparty/openexr/Imath/ImathVec.h +++ b/3rdparty/openexr/Imath/ImathVec.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -46,6 +46,7 @@ #include "ImathExc.h" #include "ImathLimits.h" #include "ImathMath.h" +#include "ImathNamespace.h" #include @@ -56,7 +57,7 @@ #endif -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template class Vec2; template class Vec3; @@ -117,7 +118,7 @@ template class Vec2 T * getValue (); const T * getValue () const; - + //--------- // Equality //--------- @@ -224,11 +225,11 @@ template class Vec2 T length2 () const; const Vec2 & normalize (); // modifies *this - const Vec2 & normalizeExc () throw (Iex::MathExc); + const Vec2 & normalizeExc (); const Vec2 & normalizeNonNull (); Vec2 normalized () const; // does not modify *this - Vec2 normalizedExc () const throw (Iex::MathExc); + Vec2 normalizedExc () const; Vec2 normalizedNonNull () const; @@ -251,7 +252,7 @@ template class Vec2 //-------------------------------------------------------------- // Base type -- in templates, which accept a parameter, V, which - // could be either a Vec2, a Vec3, or a Vec4 you can + // could be either a Vec2, a Vec3, or a Vec4 you can // refer to T as V::BaseType //-------------------------------------------------------------- @@ -436,11 +437,11 @@ template class Vec3 T length2 () const; const Vec3 & normalize (); // modifies *this - const Vec3 & normalizeExc () throw (Iex::MathExc); + const Vec3 & normalizeExc (); const Vec3 & normalizeNonNull (); Vec3 normalized () const; // does not modify *this - Vec3 normalizedExc () const throw (Iex::MathExc); + Vec3 normalizedExc () const; Vec3 normalizedNonNull () const; @@ -463,7 +464,7 @@ template class Vec3 //-------------------------------------------------------------- // Base type -- in templates, which accept a parameter, V, which - // could be either a Vec2, a Vec3, or a Vec4 you can + // could be either a Vec2, a Vec3, or a Vec4 you can // refer to T as V::BaseType //-------------------------------------------------------------- @@ -484,7 +485,7 @@ template class Vec4 // Access to elements //------------------- - T x, y, z, w; + T x, y, z, w; T & operator [] (int i); const T & operator [] (int i) const; @@ -618,11 +619,11 @@ template class Vec4 T length2 () const; const Vec4 & normalize (); // modifies *this - const Vec4 & normalizeExc () throw (Iex::MathExc); + const Vec4 & normalizeExc (); const Vec4 & normalizeNonNull (); Vec4 normalized () const; // does not modify *this - Vec4 normalizedExc () const throw (Iex::MathExc); + Vec4 normalizedExc () const; Vec4 normalizedNonNull () const; @@ -645,7 +646,7 @@ template class Vec4 //-------------------------------------------------------------- // Base type -- in templates, which accept a parameter, V, which - // could be either a Vec2, a Vec3, or a Vec4 you can + // could be either a Vec2, a Vec3, or a Vec4 you can // refer to T as V::BaseType //-------------------------------------------------------------- @@ -710,7 +711,7 @@ template <> const Vec2 & Vec2::normalize (); template <> const Vec2 & -Vec2::normalizeExc () throw (Iex::MathExc); +Vec2::normalizeExc (); template <> const Vec2 & Vec2::normalizeNonNull (); @@ -719,7 +720,7 @@ template <> Vec2 Vec2::normalized () const; template <> Vec2 -Vec2::normalizedExc () const throw (Iex::MathExc); +Vec2::normalizedExc () const; template <> Vec2 Vec2::normalizedNonNull () const; @@ -734,7 +735,7 @@ template <> const Vec2 & Vec2::normalize (); template <> const Vec2 & -Vec2::normalizeExc () throw (Iex::MathExc); +Vec2::normalizeExc (); template <> const Vec2 & Vec2::normalizeNonNull (); @@ -743,7 +744,7 @@ template <> Vec2 Vec2::normalized () const; template <> Vec2 -Vec2::normalizedExc () const throw (Iex::MathExc); +Vec2::normalizedExc () const; template <> Vec2 Vec2::normalizedNonNull () const; @@ -758,7 +759,7 @@ template <> const Vec3 & Vec3::normalize (); template <> const Vec3 & -Vec3::normalizeExc () throw (Iex::MathExc); +Vec3::normalizeExc (); template <> const Vec3 & Vec3::normalizeNonNull (); @@ -767,7 +768,7 @@ template <> Vec3 Vec3::normalized () const; template <> Vec3 -Vec3::normalizedExc () const throw (Iex::MathExc); +Vec3::normalizedExc () const; template <> Vec3 Vec3::normalizedNonNull () const; @@ -782,7 +783,7 @@ template <> const Vec3 & Vec3::normalize (); template <> const Vec3 & -Vec3::normalizeExc () throw (Iex::MathExc); +Vec3::normalizeExc (); template <> const Vec3 & Vec3::normalizeNonNull (); @@ -791,7 +792,7 @@ template <> Vec3 Vec3::normalized () const; template <> Vec3 -Vec3::normalizedExc () const throw (Iex::MathExc); +Vec3::normalizedExc () const; template <> Vec3 Vec3::normalizedNonNull () const; @@ -805,7 +806,7 @@ template <> const Vec4 & Vec4::normalize (); template <> const Vec4 & -Vec4::normalizeExc () throw (Iex::MathExc); +Vec4::normalizeExc (); template <> const Vec4 & Vec4::normalizeNonNull (); @@ -814,7 +815,7 @@ template <> Vec4 Vec4::normalized () const; template <> Vec4 -Vec4::normalizedExc () const throw (Iex::MathExc); +Vec4::normalizedExc () const; template <> Vec4 Vec4::normalizedNonNull () const; @@ -829,7 +830,7 @@ template <> const Vec4 & Vec4::normalize (); template <> const Vec4 & -Vec4::normalizeExc () throw (Iex::MathExc); +Vec4::normalizeExc (); template <> const Vec4 & Vec4::normalizeNonNull (); @@ -838,7 +839,7 @@ template <> Vec4 Vec4::normalized () const; template <> Vec4 -Vec4::normalizedExc () const throw (Iex::MathExc); +Vec4::normalizedExc () const; template <> Vec4 Vec4::normalizedNonNull () const; @@ -981,8 +982,8 @@ bool Vec2::equalWithAbsError (const Vec2 &v, T e) const { for (int i = 0; i < 2; i++) - if (!Imath::equalWithAbsError ((*this)[i], v[i], e)) - return false; + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) + return false; return true; } @@ -992,8 +993,8 @@ bool Vec2::equalWithRelError (const Vec2 &v, T e) const { for (int i = 0; i < 2; i++) - if (!Imath::equalWithRelError ((*this)[i], v[i], e)) - return false; + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) + return false; return true; } @@ -1145,14 +1146,14 @@ Vec2::lengthTiny () const { T absX = (x >= T (0))? x: -x; T absY = (y >= T (0))? y: -y; - + T max = absX; if (max < absY) - max = absY; + max = absY; if (max == T (0)) - return T (0); + return T (0); // // Do not replace the divisions by max with multiplications by 1/max. @@ -1173,7 +1174,7 @@ Vec2::length () const T length2 = dot (*this); if (length2 < T (2) * limits::smallest()) - return lengthTiny(); + return lengthTiny(); return Math::sqrt (length2); } @@ -1199,8 +1200,8 @@ Vec2::normalize () // produce results less than or equal to 1. // - x /= l; - y /= l; + x /= l; + y /= l; } return *this; @@ -1208,12 +1209,12 @@ Vec2::normalize () template const Vec2 & -Vec2::normalizeExc () throw (Iex::MathExc) +Vec2::normalizeExc () { T l = length(); if (l == T (0)) - throw NullVecExc ("Cannot normalize null vector."); + throw NullVecExc ("Cannot normalize null vector."); x /= l; y /= l; @@ -1238,19 +1239,19 @@ Vec2::normalized () const T l = length(); if (l == T (0)) - return Vec2 (T (0)); + return Vec2 (T (0)); return Vec2 (x / l, y / l); } template Vec2 -Vec2::normalizedExc () const throw (Iex::MathExc) +Vec2::normalizedExc () const { T l = length(); if (l == T (0)) - throw NullVecExc ("Cannot normalize null vector."); + throw NullVecExc ("Cannot normalize null vector."); return Vec2 (x / l, y / l); } @@ -1359,7 +1360,7 @@ Vec3::Vec3 (const Vec4 &v, InfException) if (absW < 1) { T m = baseTypeMax() * absW; - + if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m) throw InfPointExc ("Cannot normalize point at infinity."); } @@ -1444,8 +1445,8 @@ bool Vec3::equalWithAbsError (const Vec3 &v, T e) const { for (int i = 0; i < 3; i++) - if (!Imath::equalWithAbsError ((*this)[i], v[i], e)) - return false; + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) + return false; return true; } @@ -1455,8 +1456,8 @@ bool Vec3::equalWithRelError (const Vec3 &v, T e) const { for (int i = 0; i < 3; i++) - if (!Imath::equalWithRelError ((*this)[i], v[i], e)) - return false; + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) + return false; return true; } @@ -1480,8 +1481,8 @@ inline Vec3 Vec3::cross (const Vec3 &v) const { return Vec3 (y * v.z - z * v.y, - z * v.x - x * v.z, - x * v.y - y * v.x); + z * v.x - x * v.z, + x * v.y - y * v.x); } template @@ -1502,8 +1503,8 @@ inline Vec3 Vec3::operator % (const Vec3 &v) const { return Vec3 (y * v.z - z * v.y, - z * v.x - x * v.z, - x * v.y - y * v.x); + z * v.x - x * v.z, + x * v.y - y * v.x); } template @@ -1632,17 +1633,17 @@ Vec3::lengthTiny () const T absX = (x >= T (0))? x: -x; T absY = (y >= T (0))? y: -y; T absZ = (z >= T (0))? z: -z; - + T max = absX; if (max < absY) - max = absY; + max = absY; if (max < absZ) - max = absZ; + max = absZ; if (max == T (0)) - return T (0); + return T (0); // // Do not replace the divisions by max with multiplications by 1/max. @@ -1664,7 +1665,7 @@ Vec3::length () const T length2 = dot (*this); if (length2 < T (2) * limits::smallest()) - return lengthTiny(); + return lengthTiny(); return Math::sqrt (length2); } @@ -1690,9 +1691,9 @@ Vec3::normalize () // produce results less than or equal to 1. // - x /= l; - y /= l; - z /= l; + x /= l; + y /= l; + z /= l; } return *this; @@ -1700,12 +1701,12 @@ Vec3::normalize () template const Vec3 & -Vec3::normalizeExc () throw (Iex::MathExc) +Vec3::normalizeExc () { T l = length(); if (l == T (0)) - throw NullVecExc ("Cannot normalize null vector."); + throw NullVecExc ("Cannot normalize null vector."); x /= l; y /= l; @@ -1732,19 +1733,19 @@ Vec3::normalized () const T l = length(); if (l == T (0)) - return Vec3 (T (0)); + return Vec3 (T (0)); return Vec3 (x / l, y / l, z / l); } template Vec3 -Vec3::normalizedExc () const throw (Iex::MathExc) +Vec3::normalizedExc () const { T l = length(); if (l == T (0)) - throw NullVecExc ("Cannot normalize null vector."); + throw NullVecExc ("Cannot normalize null vector."); return Vec3 (x / l, y / l, z / l); } @@ -1865,7 +1866,7 @@ bool Vec4::equalWithAbsError (const Vec4 &v, T e) const { for (int i = 0; i < 4; i++) - if (!Imath::equalWithAbsError ((*this)[i], v[i], e)) + if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false; return true; @@ -1876,7 +1877,7 @@ bool Vec4::equalWithRelError (const Vec4 &v, T e) const { for (int i = 0; i < 4; i++) - if (!Imath::equalWithRelError ((*this)[i], v[i], e)) + if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false; return true; @@ -2031,7 +2032,7 @@ Vec4::lengthTiny () const T absY = (y >= T (0))? y: -y; T absZ = (z >= T (0))? z: -z; T absW = (w >= T (0))? w: -w; - + T max = absX; if (max < absY) @@ -2105,7 +2106,7 @@ Vec4::normalize () template const Vec4 & -Vec4::normalizeExc () throw (Iex::MathExc) +Vec4::normalizeExc () { T l = length(); @@ -2146,7 +2147,7 @@ Vec4::normalized () const template Vec4 -Vec4::normalizedExc () const throw (Iex::MathExc) +Vec4::normalizedExc () const { T l = length(); @@ -2221,6 +2222,6 @@ operator * (T a, const Vec4 &v) #pragma warning(pop) #endif -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHVEC_H diff --git a/3rdparty/openexr/Imath/ImathVecAlgo.h b/3rdparty/openexr/Imath/ImathVecAlgo.h index 9b92d3fc4d..28bab6bdd0 100644 --- a/3rdparty/openexr/Imath/ImathVecAlgo.h +++ b/3rdparty/openexr/Imath/ImathVecAlgo.h @@ -1,10 +1,10 @@ /////////////////////////////////////////////////////////////////////////// // -// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas +// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC -// +// // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -16,8 +16,8 @@ // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// +// from this software without specific prior written permission. +// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -49,8 +49,9 @@ #include "ImathVec.h" #include "ImathLimits.h" +#include "ImathNamespace.h" -namespace Imath { +IMATH_INTERNAL_NAMESPACE_HEADER_ENTER //----------------------------------------------------------------- @@ -83,7 +84,7 @@ template Vec reflect (const Vec &s, const Vec &t); template Vec closestVertex (const Vec &v0, const Vec &v1, - const Vec &v2, + const Vec &v2, const Vec &p); //--------------- @@ -116,7 +117,7 @@ template Vec closestVertex(const Vec &v0, const Vec &v1, - const Vec &v2, + const Vec &v2, const Vec &p) { Vec nearest = v0; @@ -141,6 +142,6 @@ closestVertex(const Vec &v0, } -} // namespace Imath +IMATH_INTERNAL_NAMESPACE_HEADER_EXIT -#endif +#endif // INCLUDED_IMATHVECALGO_H diff --git a/3rdparty/openexr/OpenEXRConfig.h.cmakein b/3rdparty/openexr/OpenEXRConfig.h.cmakein index 0a6b592c76..33b2cc9981 100644 --- a/3rdparty/openexr/OpenEXRConfig.h.cmakein +++ b/3rdparty/openexr/OpenEXRConfig.h.cmakein @@ -5,14 +5,14 @@ // used by any OpenEXR library or application code. // -#undef HAVE_LINUX_PROCFS +#cmakedefine OPENEXR_IMF_HAVE_LINUX_PROCFS // // Define and set to 1 if the target system is a Darwin-based system // (e.g., OS X). // -#undef HAVE_DARWIN +#cmakedefine OPENEXR_IMF_HAVE_DARWIN // // Define and set to 1 if the target system has a complete @@ -20,17 +20,53 @@ // formatter. // -#undef HAVE_COMPLETE_IOMANIP +#cmakedefine OPENEXR_IMF_HAVE_COMPLETE_IOMANIP // // Define and set to 1 if the target system has support for large // stack sizes. // -#undef HAVE_LARGE_STACK +#cmakedefine OPENEXR_IMF_HAVE_LARGE_STACK + +// +// Define if we can support GCC style inline asm with AVX instructions +// + +#cmakedefine OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX + +// +// Define if we can use sysconf(_SC_NPROCESSORS_ONLN) to get CPU count +// + +#cmakedefine OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN + +// +// Current internal library namepace name +// +#define OPENEXR_IMF_INTERNAL_NAMESPACE_CUSTOM @OPENEXR_IMF_INTERNAL_NAMESPACE_CUSTOM@ +#define OPENEXR_IMF_INTERNAL_NAMESPACE @OPENEXR_IMF_INTERNAL_NAMESPACE@ + +// +// Current public user namepace name +// + +#define OPENEXR_IMF_NAMESPACE_CUSTOM @OPENEXR_IMF_NAMESPACE_CUSTOM@ +#define OPENEXR_IMF_NAMESPACE @OPENEXR_IMF_NAMESPACE@ // // Version string for runtime access // -#define OPENEXR_VERSION_STRING "1.7.1" -#define OPENEXR_PACKAGE_STRING "OpenEXR 1.7.1" + +#define OPENEXR_VERSION_STRING @OPENEXR_VERSION_STRING@ +#define OPENEXR_PACKAGE_STRING @OPENEXR_PACKAGE_STRING@ + +#define OPENEXR_VERSION_MAJOR @OPENEXR_VERSION_MAJOR@ +#define OPENEXR_VERSION_MINOR @OPENEXR_VERSION_MINOR@ +#define OPENEXR_VERSION_PATCH @OPENEXR_VERSION_PATCH@ + +// Version as a single hex number, e.g. 0x01000300 == 1.0.3 +#define OPENEXR_VERSION_HEX ((OPENEXR_VERSION_MAJOR << 24) | \ + (OPENEXR_VERSION_MINOR << 16) | \ + (OPENEXR_VERSION_PATCH << 8)) + diff --git a/3rdparty/openexr/fix_msvc2013_errors.patch b/3rdparty/openexr/fix_msvc2013_errors.patch deleted file mode 100644 index 0ce106f13b..0000000000 --- a/3rdparty/openexr/fix_msvc2013_errors.patch +++ /dev/null @@ -1,72 +0,0 @@ -diff --git a/3rdparty/openexr/IlmImf/ImfAcesFile.cpp b/3rdparty/openexr/IlmImf/ImfAcesFile.cpp -index de4bf83..9418b9d 100644 ---- a/3rdparty/openexr/IlmImf/ImfAcesFile.cpp -+++ b/3rdparty/openexr/IlmImf/ImfAcesFile.cpp -@@ -42,6 +42,7 @@ - #include - #include - #include -+#include // for std::max() - - using namespace std; - using namespace Imath; -diff --git a/3rdparty/openexr/IlmImf/ImfOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfOutputFile.cpp -index 8831ec9..e69b92b 100644 ---- a/3rdparty/openexr/IlmImf/ImfOutputFile.cpp -+++ b/3rdparty/openexr/IlmImf/ImfOutputFile.cpp -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include // for std::max() - - - namespace Imf { -diff --git a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp -index f7a12a3..5d8b522 100644 ---- a/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp -+++ b/3rdparty/openexr/IlmImf/ImfScanLineInputFile.cpp -@@ -56,6 +56,7 @@ - #include - #include - #include -+#include // for std::max() - - - namespace Imf { -diff --git a/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp b/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp -index 57f52f1..9588e78 100644 ---- a/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp -+++ b/3rdparty/openexr/IlmImf/ImfTiledMisc.cpp -@@ -43,6 +43,7 @@ - #include "Iex.h" - #include - #include -+#include // for std::max() - - - namespace Imf { -diff --git a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp -index 0882106..0bc3cb3 100644 ---- a/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp -+++ b/3rdparty/openexr/IlmImf/ImfTiledOutputFile.cpp -@@ -63,6 +63,7 @@ - #include - #include - #include -+#include // for std::max() - - - namespace Imf { -diff --git a/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp b/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp -index f0d2ed6..7ddc649 100644 ---- a/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp -+++ b/3rdparty/openexr/Imath/ImathMatrixAlgo.cpp -@@ -44,6 +44,7 @@ - - #include "ImathMatrixAlgo.h" - #include -+#include // for std::max() - - #if defined(OPENEXR_DLL) - #define EXPORT_CONST __declspec(dllexport) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb46b301d4..9f051d0547 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,8 +294,8 @@ OCV_OPTION(WITH_JPEG "Include JPEG support" ON OCV_OPTION(WITH_WEBP "Include WebP support" ON VISIBLE_IF NOT WINRT VERIFY HAVE_WEBP) -OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" ON - VISIBLE_IF NOT IOS AND NOT WINRT +OCV_OPTION(WITH_OPENEXR "Include ILM support via OpenEXR" BUILD_OPENEXR OR NOT CMAKE_CROSSCOMPILING + VISIBLE_IF NOT APPLE_FRAMEWORK AND NOT WINRT VERIFY HAVE_OPENEXR) OCV_OPTION(WITH_OPENGL "Include OpenGL support" OFF VISIBLE_IF NOT ANDROID AND NOT WINRT @@ -1381,7 +1381,11 @@ if(WITH_JASPER OR HAVE_JASPER) endif() if(WITH_OPENEXR OR HAVE_OPENEXR) - status(" OpenEXR:" OPENEXR_FOUND THEN "${OPENEXR_LIBRARIES} (ver ${OPENEXR_VERSION})" ELSE "build (ver ${OPENEXR_VERSION})") + if(HAVE_OPENEXR) + status(" OpenEXR:" OPENEXR_FOUND THEN "${OPENEXR_LIBRARIES} (ver ${OPENEXR_VERSION})" ELSE "build (ver ${OPENEXR_VERSION})") + else() + status(" OpenEXR:" "NO") + endif() endif() if(WITH_GDAL OR HAVE_GDAL) diff --git a/cmake/OpenCVFindLibsGrfmt.cmake b/cmake/OpenCVFindLibsGrfmt.cmake index 9f18e2bf62..fcf716b976 100644 --- a/cmake/OpenCVFindLibsGrfmt.cmake +++ b/cmake/OpenCVFindLibsGrfmt.cmake @@ -211,21 +211,22 @@ endif() # --- OpenEXR (optional) --- if(WITH_OPENEXR) - if(BUILD_OPENEXR) - ocv_clear_vars(OPENEXR_FOUND) - else() + ocv_clear_vars(HAVE_OPENEXR) + if(NOT BUILD_OPENEXR) include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindOpenEXR.cmake") endif() - if(NOT OPENEXR_FOUND) + if(OPENEXR_FOUND) + set(HAVE_OPENEXR YES) + else() ocv_clear_vars(OPENEXR_INCLUDE_PATHS OPENEXR_LIBRARIES OPENEXR_ILMIMF_LIBRARY OPENEXR_VERSION) set(OPENEXR_LIBRARIES IlmImf) - set(OPENEXR_ILMIMF_LIBRARY IlmImf) add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/openexr") + if(OPENEXR_VERSION) # check via TARGET doesn't work + set(HAVE_OPENEXR YES) + endif() endif() - - set(HAVE_OPENEXR YES) endif() # --- GDAL (optional) ---