HDR formats support and HDR making. Code only.
authorFedor Morozov <f-morozov@ya.ru>
Sun, 23 Jun 2013 10:19:09 +0000 (14:19 +0400)
committerFedor Morozov <f-morozov@ya.ru>
Sun, 23 Jun 2013 10:19:09 +0000 (14:19 +0400)
12 files changed:
CMakeFiles/2.8.11.1/CompilerIdCXX/CMakeCXXCompilerId.cpp [new file with mode: 0644]
modules/highgui/CMakeLists.txt
modules/highgui/src/grfmt_hdr.cpp [new file with mode: 0644]
modules/highgui/src/grfmt_hdr.hpp [new file with mode: 0644]
modules/highgui/src/grfmt_tiff.cpp
modules/highgui/src/grfmt_tiff.hpp
modules/highgui/src/grfmts.hpp
modules/highgui/src/loadsave.cpp
modules/highgui/src/rgbe.cpp [new file with mode: 0644]
modules/highgui/src/rgbe.hpp [new file with mode: 0644]
modules/photo/include/opencv2/photo.hpp
modules/photo/src/hdr_fusion.cpp [new file with mode: 0644]

diff --git a/CMakeFiles/2.8.11.1/CompilerIdCXX/CMakeCXXCompilerId.cpp b/CMakeFiles/2.8.11.1/CompilerIdCXX/CMakeCXXCompilerId.cpp
new file mode 100644 (file)
index 0000000..17c8fd9
--- /dev/null
@@ -0,0 +1,372 @@
+/* This source file must have a .cpp extension so that all C++ compilers
+   recognize the extension without flags.  Borland does not know .cxx for
+   example.  */
+#ifndef __cplusplus
+# error "A C compiler has been selected for C++."
+#endif
+
+/* Version number components: V=Version, R=Revision, P=Patch
+   Version date components:   YYYY=Year, MM=Month,   DD=Day  */
+
+#if defined(__COMO__)
+# define COMPILER_ID "Comeau"
+  /* __COMO_VERSION__ = VRR */
+# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
+# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
+
+#elif defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+  /* __INTEL_COMPILER = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER    % 10)
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+  /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+#  define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+#  define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__     & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+  /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "Watcom"
+  /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100)
+
+#elif defined(__SUNPRO_CC)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_CC >= 0x5100
+   /* __SUNPRO_CC = 0xVRRP */
+#  define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
+#  define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
+#  define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC    & 0xF)
+# else
+   /* __SUNPRO_CC = 0xVRP */
+#  define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
+#  define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
+#  define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC    & 0xF)
+# endif
+
+#elif defined(__HP_aCC)
+# define COMPILER_ID "HP"
+  /* __HP_aCC = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_aCC     % 100)
+
+#elif defined(__DECCXX)
+# define COMPILER_ID "Compaq"
+  /* __DECCXX_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000  % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER         % 10000)
+
+#elif defined(__IBMCPP__)
+# if defined(__COMPILER_VER__)
+#  define COMPILER_ID "zOS"
+# else
+#  if __IBMCPP__ >= 800
+#   define COMPILER_ID "XL"
+#  else
+#   define COMPILER_ID "VisualAge"
+#  endif
+   /* __IBMCPP__ = VRP */
+#  define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+#  define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+#  define COMPILER_VERSION_PATCH DEC(__IBMCPP__    % 10)
+# endif
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+#  define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+  /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000   % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__        % 1000)
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__GNUC__)
+# define COMPILER_ID "GNU"
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# if defined(__GNUC_PATCHLEVEL__)
+#  define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+  /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+#  if _MSC_VER >= 1400
+    /* _MSC_FULL_VER = VVRRPPPPP */
+#   define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+#  else
+    /* _MSC_FULL_VER = VVRRPPPP */
+#   define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+#  endif
+# endif
+# if defined(_MSC_BUILD)
+#  define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+/* Analog VisualDSP++ >= 4.5.6 */
+#elif defined(__VISUALDSPVERSION__)
+# define COMPILER_ID "ADSP"
+  /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8  & 0xFF)
+
+/* Analog VisualDSP++ < 4.5.6 */
+#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+
+#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION)
+# define COMPILER_ID "MIPSpro"
+# if defined(_SGI_COMPILER_VERSION)
+  /* _SGI_COMPILER_VERSION = VRP */
+#  define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100)
+#  define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10)
+#  define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION    % 10)
+# else
+  /* _COMPILER_VERSION = VRP */
+#  define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100)
+#  define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10)
+#  define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION    % 10)
+# endif
+
+/* This compiler is either not known or is too old to define an
+   identification macro.  Try to identify the platform and guess that
+   it is the native compiler.  */
+#elif defined(__sgi)
+# define COMPILER_ID "MIPSpro"
+
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+   getting matched.  Store it in a pointer rather than an array
+   because some compilers will just produce instructions to fill the
+   array rather than assigning a pointer to a static array.  */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+
+/* Identify known platforms by name.  */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__sgi) || defined(__sgi__) || defined(_SGI)
+# define PLATFORM_ID "IRIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#else /* unknown platform */
+# define PLATFORM_ID ""
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+   the architecture of the compiler being used.  This is because
+   the compilers do not have flags that can change the architecture,
+   but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+#  define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+#  define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+#  define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM)
+#  define ARCHITECTURE_ID "ARM"
+
+# elif defined(_M_MIPS)
+#  define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+#  define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+#  define ARCHITECTURE_ID ""
+# endif
+
+#else
+#  define ARCHITECTURE_ID ""
+#endif
+
+/* Convert integer to decimal digit literals.  */
+#define DEC(n)                   \
+  ('0' + (((n) / 10000000)%10)), \
+  ('0' + (((n) / 1000000)%10)),  \
+  ('0' + (((n) / 100000)%10)),   \
+  ('0' + (((n) / 10000)%10)),    \
+  ('0' + (((n) / 1000)%10)),     \
+  ('0' + (((n) / 100)%10)),      \
+  ('0' + (((n) / 10)%10)),       \
+  ('0' +  ((n) % 10))
+
+/* Convert integer to hex digit literals.  */
+#define HEX(n)             \
+  ('0' + ((n)>>28 & 0xF)), \
+  ('0' + ((n)>>24 & 0xF)), \
+  ('0' + ((n)>>20 & 0xF)), \
+  ('0' + ((n)>>16 & 0xF)), \
+  ('0' + ((n)>>12 & 0xF)), \
+  ('0' + ((n)>>8  & 0xF)), \
+  ('0' + ((n)>>4  & 0xF)), \
+  ('0' + ((n)     & 0xF))
+
+/* Construct a string literal encoding the version number components. */
+#ifdef COMPILER_VERSION_MAJOR
+char const info_version[] = {
+  'I', 'N', 'F', 'O', ':',
+  'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+  COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+  '.', COMPILER_VERSION_MINOR,
+#  ifdef COMPILER_VERSION_PATCH
+   '.', COMPILER_VERSION_PATCH,
+#   ifdef COMPILER_VERSION_TWEAK
+    '.', COMPILER_VERSION_TWEAK,
+#   endif
+#  endif
+# endif
+  ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+   getting matched.  Store it in a pointer rather than an array
+   because some compilers will just produce instructions to fill the
+   array rather than assigning a pointer to a static array.  */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+  int require = 0;
+  require += info_compiler[argc];
+  require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+  require += info_version[argc];
+#endif
+  (void)argv;
+  return require;
+}
index 8244660..aec364a 100644 (file)
@@ -55,6 +55,8 @@ file(GLOB grfmt_hdrs src/grfmt*.hpp)
 file(GLOB grfmt_srcs src/grfmt*.cpp)
 list(APPEND grfmt_hdrs src/bitstrm.hpp)
 list(APPEND grfmt_srcs src/bitstrm.cpp)
+list(APPEND grfmt_hdrs src/rgbe.hpp)
+list(APPEND grfmt_srcs src/rgbe.cpp)
 
 source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs})
 
diff --git a/modules/highgui/src/grfmt_hdr.cpp b/modules/highgui/src/grfmt_hdr.cpp
new file mode 100644 (file)
index 0000000..a5aab30
--- /dev/null
@@ -0,0 +1,152 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's 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.
+//
+//   * The name of the copyright holders may not 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 Intel Corporation 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.
+//
+//M*/
+
+#include "grfmt_hdr.hpp"
+#include "rgbe.hpp"
+
+namespace cv
+{
+HdrDecoder::HdrDecoder()
+{
+       m_signature = "#?RGBE";
+       m_signature_alt = "#?RADIANCE";
+       file = NULL;
+       m_type = CV_32FC3;
+}
+
+HdrDecoder::~HdrDecoder()
+{
+}
+
+size_t HdrDecoder::signatureLength() const
+{
+       return m_signature.size() > m_signature_alt.size() ?
+                  m_signature.size() : m_signature_alt.size();
+}
+
+bool  HdrDecoder::readHeader()
+{
+       file = fopen(m_filename.c_str(), "rb");
+       if(!file) {
+               CV_Error(Error::StsError, "HDR decoder: can't open file");
+       }
+       RGBE_ReadHeader(file, &m_width, &m_height, NULL);
+       if(m_width <= 0 || m_height <= 0) {
+               CV_Error(Error::StsError, "HDR decoder: invalid image size");
+       }
+       return true;
+}
+
+bool HdrDecoder::readData(Mat& img)
+{
+       if(!file) {
+               readHeader();
+       }
+       if(img.cols != m_width || img.rows != m_height ||
+          img.type() != CV_32FC3) {
+               CV_Error(Error::StsError, "HDR decoder: bad mat");
+       }
+       RGBE_ReadPixels_RLE(file, const_cast<float*>(img.ptr<float>()), img.cols, img.rows);
+       fclose(file); file = NULL;
+       return true;
+}
+
+bool HdrDecoder::checkSignature( const String& signature ) const
+{
+       if(signature.size() >= (m_signature.size()) && 
+          !memcmp(signature.c_str(), m_signature.c_str(), m_signature.size()))
+          return true;
+       if(signature.size() >= (m_signature.size()) && 
+          !memcmp(signature.c_str(), m_signature_alt.c_str(), m_signature_alt.size()))
+          return true;
+       return false;
+}
+
+ImageDecoder HdrDecoder::newDecoder() const
+{
+       return new HdrDecoder;
+}
+
+HdrEncoder::HdrEncoder()
+{
+       m_description = "Radiance HDR (*.hdr;*.pic)";
+}
+
+HdrEncoder::~HdrEncoder()
+{
+}
+
+bool HdrEncoder::write( const Mat& img, const std::vector<int>& params )
+{
+       if(img.type() != CV_32FC3) {
+               CV_Error(Error::StsBadArg, "HDR encoder: need 32FC3 mat");
+       }
+       if(!(params.empty() || params[0] == HDR_NONE || params[0] == HDR_RLE)) {
+               CV_Error(Error::StsBadArg, "HDR encoder: wrong compression param");
+       }
+
+       FILE *fout = fopen(m_filename.c_str(), "wb");
+       if(!fout) {
+               CV_Error(Error::StsError, "HDR encoder: can't open file");
+       }
+
+       RGBE_WriteHeader(fout, img.cols, img.rows, NULL);
+       if(params.empty() || params[0] == HDR_RLE) {
+               RGBE_WritePixels_RLE(fout, const_cast<float*>(img.ptr<float>()), img.cols, img.rows);
+       } else {
+               RGBE_WritePixels(fout, const_cast<float*>(img.ptr<float>()), img.cols * img.rows);
+       }
+
+       fclose(fout);
+       return true;
+}
+
+ImageEncoder HdrEncoder::newEncoder() const
+{
+       return new HdrEncoder;
+}
+
+bool HdrEncoder::isFormatSupported( int depth ) const {
+       return depth == CV_32F;
+}
+
+}
diff --git a/modules/highgui/src/grfmt_hdr.hpp b/modules/highgui/src/grfmt_hdr.hpp
new file mode 100644 (file)
index 0000000..5267782
--- /dev/null
@@ -0,0 +1,88 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's 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.
+//
+//   * The name of the copyright holders may not 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 Intel Corporation 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.
+//
+//M*/
+
+#ifndef _GRFMT_HDR_H_
+#define _GRFMT_HDR_H_
+
+#include "grfmt_base.hpp"
+
+namespace cv
+{
+
+enum HdrCompression
+{
+    HDR_NONE = 0,
+    HDR_RLE = 1
+};
+
+// Radiance rgbe (.hdr) reader
+class HdrDecoder : public BaseImageDecoder
+{
+public:
+       HdrDecoder();
+       ~HdrDecoder();
+       bool readHeader();
+       bool readData( Mat& img );
+       bool checkSignature( const String& signature ) const;
+       ImageDecoder newDecoder() const;
+       size_t signatureLength() const;
+protected:
+       String m_signature_alt;
+       FILE *file;
+};
+
+// ... writer
+class HdrEncoder : public BaseImageEncoder
+{
+public:
+       HdrEncoder();
+       ~HdrEncoder();
+       bool write( const Mat& img, const std::vector<int>& params );
+       ImageEncoder newEncoder() const;
+       bool isFormatSupported( int depth ) const;
+protected:
+       
+};
+
+}
+
+#endif/*_GRFMT_HDR_H_*/
\ No newline at end of file
index a0d53f3..51d17ce 100644 (file)
@@ -71,6 +71,7 @@ TiffDecoder::TiffDecoder()
         TIFFSetErrorHandler( GrFmtSilentTIFFErrorHandler );
         TIFFSetWarningHandler( GrFmtSilentTIFFErrorHandler );
     }
+       m_hdr = false;
 }
 
 
@@ -133,6 +134,14 @@ bool TiffDecoder::readHeader()
 
             m_width = wdth;
             m_height = hght;
+                       if((bpp == 32 && ncn == 3) || photometric == PHOTOMETRIC_LOGLUV) 
+                       {
+                               m_type = CV_32FC3; 
+                               m_hdr = true;
+                               return true;
+                       }
+                       m_hdr = false;
+
             if( bpp > 8 &&
                ((photometric != 2 && photometric != 1) ||
                 (ncn != 1 && ncn != 3 && ncn != 4)))
@@ -171,6 +180,10 @@ bool TiffDecoder::readHeader()
 
 bool  TiffDecoder::readData( Mat& img )
 {
+       if(m_hdr && img.type() == CV_32FC3) 
+       {
+               return readHdrData(img);
+       }
     bool result = false;
     bool color = img.channels() > 1;
     uchar* data = img.data;
@@ -380,6 +393,46 @@ bool  TiffDecoder::readData( Mat& img )
     return result;
 }
 
+bool TiffDecoder::readHdrData(Mat& img) 
+{
+       int rows_per_strip = 0, photometric = 0;
+       if(!m_tif) 
+       {
+               return false;
+       }
+       TIFF *tif = static_cast<TIFF*>(m_tif);
+       TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip);
+    TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric );
+       TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT);
+       int size = 3 * m_width * m_height * sizeof (float);
+       int strip_size = 3 * m_width * rows_per_strip;
+       float *ptr = img.ptr<float>();
+       for (size_t i = 0; i < TIFFNumberOfStrips(tif); i++, ptr += strip_size) 
+       {       
+               TIFFReadEncodedStrip(tif, i, ptr, size);
+               size -= strip_size * sizeof(float);
+       }
+       close();
+       ptr = img.ptr<float>();
+       for(size_t i = 0; i < img.total(); i++, ptr += 3) 
+       {
+               if(photometric == PHOTOMETRIC_LOGLUV) 
+               {
+                       float r =  3.240479f * ptr[0] + -1.537150f * ptr[1] + -0.498535f * ptr[2];
+                       float g = -0.969256f * ptr[0] +  1.875991f * ptr[1] +  0.041556f * ptr[2];
+                       float b =  0.055648f * ptr[0] + -0.204043f * ptr[1] +  1.057311f * ptr[2];
+                       ptr[0] = b; ptr[1] = g; ptr[2] = r;
+               } 
+               else 
+               {
+                       float tmp = ptr[0];
+                       ptr[0] = ptr[2];
+                       ptr[2] = tmp;
+               }
+       }
+       return true;
+}
+
 #endif
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -405,7 +458,11 @@ ImageEncoder TiffEncoder::newEncoder() const
 
 bool TiffEncoder::isFormatSupported( int depth ) const
 {
-    return depth == CV_8U || depth == CV_16U;
+#ifdef HAVE_TIFF
+    return depth == CV_8U || depth == CV_16U || depth == CV_32F;
+#else 
+       return depth == CV_8U || depth == CV_16U;
+#endif
 }
 
 void  TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag,
@@ -557,6 +614,39 @@ bool  TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params)
     return true;
 }
 
+bool TiffEncoder::writeHdr(const Mat& img)
+{
+       float *ptr = const_cast<float*>(img.ptr<float>());
+       for(size_t i = 0; i < img.total(); i++, ptr += 3) 
+       {
+               float x = 0.412453f * ptr[2] + 0.357580f * ptr[1] + 0.180423f * ptr[0];
+               float y = 0.212671f * ptr[2] + 0.715160f * ptr[1] + 0.072169f * ptr[0];
+               float z = 0.019334f * ptr[2] + 0.119193f * ptr[1] + 0.950227f * ptr[0];
+               ptr[0] = x; ptr[1] = y; ptr[2] = z;
+       }
+       TIFF* tif = TIFFOpen(m_filename.c_str(), "w");
+    if (!tif) 
+       {
+        return false;
+    }
+       TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, img.cols);
+       TIFFSetField(tif, TIFFTAG_IMAGELENGTH, img.rows);
+       TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
+       TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_SGILOG);
+       TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_LOGLUV);
+       TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+       TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT);
+       TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);     
+       int strip_size = 3 * img.cols;
+       ptr = const_cast<float*>(img.ptr<float>());
+       for (int i = 0; i < img.rows; i++, ptr += strip_size) 
+       {
+               TIFFWriteEncodedStrip(tif, i, ptr, strip_size * sizeof(float));
+       }
+       TIFFClose(tif);
+       return true;
+}
+
 #endif
 
 #ifdef HAVE_TIFF
@@ -568,6 +658,12 @@ bool  TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/)
     int channels = img.channels();
     int width = img.cols, height = img.rows;
     int depth = img.depth();
+#ifdef HAVE_TIFF
+    if(img.type() == CV_32FC3) 
+       {
+               return writeHdr(img);
+       }
+#endif
 
     if (depth != CV_8U && depth != CV_16U)
         return false;
index d3745a9..b6f7fa0 100644 (file)
@@ -53,7 +53,7 @@ enum TiffCompression
 {
     TIFF_UNCOMP = 1,
     TIFF_HUFFMAN = 2,
-    TIFF_PACKBITS = 32773
+    TIFF_PACKBITS = 32773,
 };
 
 enum TiffByteOrder
@@ -108,6 +108,8 @@ public:
 protected:
     void* m_tif;
     int normalizeChannelsNumber(int channels) const;
+       bool readHdrData(Mat& img);
+       bool m_hdr;
 };
 
 #endif
@@ -130,6 +132,7 @@ protected:
                     int count, int value );
 
     bool writeLibTiff( const Mat& img, const std::vector<int>& params );
+       bool writeHdr( const Mat& img );
 };
 
 }
index 659ceb7..799a475 100644 (file)
@@ -52,5 +52,6 @@
 #include "grfmt_jpeg2000.hpp"
 #include "grfmt_exr.hpp"
 #include "grfmt_webp.hpp"
+#include "grfmt_hdr.hpp"
 
 #endif/*_GRFMTS_H_*/
index a548df5..c756916 100644 (file)
@@ -47,6 +47,7 @@
 #include "grfmts.hpp"
 #undef min
 #undef max
+#include <iostream>
 
 /****************************************************************************************\
 *                                      Image Codecs                                      *
@@ -60,6 +61,8 @@ struct ImageCodecInitializer
     {
         decoders.push_back( new BmpDecoder );
         encoders.push_back( new BmpEncoder );
+               decoders.push_back( new HdrDecoder );
+        encoders.push_back( new HdrEncoder );
     #ifdef HAVE_JPEG
         decoders.push_back( new JpegDecoder );
         encoders.push_back( new JpegEncoder );
@@ -203,7 +206,6 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 )
     decoder->setSource(filename);
     if( !decoder->readHeader() )
         return 0;
-
     CvSize size;
     size.width = decoder->width();
     size.height = decoder->height();
@@ -271,7 +273,6 @@ static bool imwrite_( const String& filename, const Mat& image,
     ImageEncoder encoder = findEncoder( filename );
     if( encoder.empty() )
         CV_Error( CV_StsError, "could not find a writer for the specified extension" );
-
     if( !encoder->isFormatSupported(image.depth()) )
     {
         CV_Assert( encoder->isFormatSupported(CV_8U) );
diff --git a/modules/highgui/src/rgbe.cpp b/modules/highgui/src/rgbe.cpp
new file mode 100644 (file)
index 0000000..2403be7
--- /dev/null
@@ -0,0 +1,450 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's 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.
+//
+//   * The name of the copyright holders may not 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 Intel Corporation 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.
+//
+//M*/
+
+#include "rgbe.hpp"
+#include <math.h>
+#include <malloc.h>
+#include <string.h>
+#include <ctype.h>
+
+// This file contains code to read and write four byte rgbe file format
+// developed by Greg Ward.  It handles the conversions between rgbe and
+// pixels consisting of floats.  The data is assumed to be an array of floats.
+// By default there are three floats per pixel in the order red, green, blue.
+// (RGBE_DATA_??? values control this.)  Only the mimimal header reading and 
+// writing is implemented.  Each routine does error checking and will return
+// a status value as defined below.  This code is intended as a skeleton so
+// feel free to modify it to suit your needs.
+
+// Some opencv specific changes have been added:
+// inline define specified, channel order changed (to ger bgr by default),
+// error handler uses CV_Error.
+//
+// posted to http://www.graphics.cornell.edu/~bjw/
+// written by Bruce Walter  (bjw@graphics.cornell.edu)  5/26/95
+// based on code written by Greg Ward
+
+#define INLINE inline
+
+/* offsets to red, green, and blue components in a data (float) pixel */
+#define RGBE_DATA_RED    2
+#define RGBE_DATA_GREEN  1
+#define RGBE_DATA_BLUE   0
+/* number of floats per pixel */
+#define RGBE_DATA_SIZE   3
+
+enum rgbe_error_codes {
+  rgbe_read_error,
+  rgbe_write_error,
+  rgbe_format_error,
+  rgbe_memory_error,
+};
+
+/* default error routine.  change this to change error handling */
+static int rgbe_error(int rgbe_error_code, char *msg)
+{
+  switch (rgbe_error_code) {
+  case rgbe_read_error:
+       CV_Error(cv::Error::StsError, "RGBE read error");
+       break;
+  case rgbe_write_error:
+       CV_Error(cv::Error::StsError, "RGBE write error");
+       break;
+  case rgbe_format_error:
+       CV_Error(cv::Error::StsError, cv::String("RGBE bad file format: ") + 
+                                                            cv::String(msg));
+       break;
+  default:
+  case rgbe_memory_error:
+       CV_Error(cv::Error::StsError, cv::String("RGBE error: \n") + 
+                                                                    cv::String(msg));
+  }
+  return RGBE_RETURN_FAILURE;
+}
+
+/* standard conversion from float pixels to rgbe pixels */
+/* note: you can remove the "inline"s if your compiler complains about it */
+static INLINE void 
+float2rgbe(unsigned char rgbe[4], float red, float green, float blue)
+{
+  float v;
+  int e;
+
+  v = red;
+  if (green > v) v = green;
+  if (blue > v) v = blue;
+  if (v < 1e-32) {
+    rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
+  }
+  else {
+    v = frexp(v,&e) * 256.0/v;
+    rgbe[0] = (unsigned char) (red * v);
+    rgbe[1] = (unsigned char) (green * v);
+    rgbe[2] = (unsigned char) (blue * v);
+    rgbe[3] = (unsigned char) (e + 128);
+  }
+}
+
+/* standard conversion from rgbe to float pixels */
+/* note: Ward uses ldexp(col+0.5,exp-(128+8)).  However we wanted pixels */
+/*       in the range [0,1] to map back into the range [0,1].            */
+static INLINE void 
+rgbe2float(float *red, float *green, float *blue, unsigned char rgbe[4])
+{
+  float f;
+
+  if (rgbe[3]) {   /*nonzero pixel*/
+    f = ldexp(1.0,rgbe[3]-(int)(128+8));
+    *red = rgbe[0] * f;
+    *green = rgbe[1] * f;
+    *blue = rgbe[2] * f;
+  }
+  else
+    *red = *green = *blue = 0.0;
+}
+
+/* default minimal header. modify if you want more information in header */
+int RGBE_WriteHeader(FILE *fp, int width, int height, rgbe_header_info *info)
+{
+  char *programtype = "RGBE";
+
+  if (info && (info->valid & RGBE_VALID_PROGRAMTYPE))
+    programtype = info->programtype;
+  if (fprintf(fp,"#?%s\n",programtype) < 0)
+    return rgbe_error(rgbe_write_error,NULL);
+  /* The #? is to identify file type, the programtype is optional. */
+  if (info && (info->valid & RGBE_VALID_GAMMA)) {
+    if (fprintf(fp,"GAMMA=%g\n",info->gamma) < 0)
+      return rgbe_error(rgbe_write_error,NULL);
+  }
+  if (info && (info->valid & RGBE_VALID_EXPOSURE)) {
+    if (fprintf(fp,"EXPOSURE=%g\n",info->exposure) < 0)
+      return rgbe_error(rgbe_write_error,NULL);
+  }
+  if (fprintf(fp,"FORMAT=32-bit_rle_rgbe\n\n") < 0)
+    return rgbe_error(rgbe_write_error,NULL);
+  if (fprintf(fp, "-Y %d +X %d\n", height, width) < 0)
+    return rgbe_error(rgbe_write_error,NULL);
+  return RGBE_RETURN_SUCCESS;
+}
+
+/* minimal header reading.  modify if you want to parse more information */
+int RGBE_ReadHeader(FILE *fp, int *width, int *height, rgbe_header_info *info)
+{
+  char buf[128];
+  int found_format;
+  float tempf;
+  int i;
+
+  found_format = 0;
+  if (info) {
+    info->valid = 0;
+    info->programtype[0] = 0;
+    info->gamma = info->exposure = 1.0;
+  }
+  if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == NULL)
+    return rgbe_error(rgbe_read_error,NULL);
+  if ((buf[0] != '#')||(buf[1] != '?')) {
+    /* if you want to require the magic token then uncomment the next line */
+    /*return rgbe_error(rgbe_format_error,"bad initial token"); */
+  }
+  else if (info) {
+    info->valid |= RGBE_VALID_PROGRAMTYPE;
+    for(i=0;i<sizeof(info->programtype)-1;i++) {
+      if ((buf[i+2] == 0) || isspace(buf[i+2]))
+       break;
+      info->programtype[i] = buf[i+2];
+    }
+    info->programtype[i] = 0;
+    if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == 0)
+      return rgbe_error(rgbe_read_error,NULL);
+  }
+  for(;;) {
+    if ((buf[0] == 0)||(buf[0] == '\n'))
+      return rgbe_error(rgbe_format_error,"no FORMAT specifier found");
+    else if (strcmp(buf,"FORMAT=32-bit_rle_rgbe\n") == 0)
+      break;       /* format found so break out of loop */
+    else if (info && (sscanf(buf,"GAMMA=%g",&tempf) == 1)) {
+      info->gamma = tempf;
+      info->valid |= RGBE_VALID_GAMMA;
+    }
+    else if (info && (sscanf(buf,"EXPOSURE=%g",&tempf) == 1)) {
+      info->exposure = tempf;
+      info->valid |= RGBE_VALID_EXPOSURE;
+    }
+    if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == 0)
+      return rgbe_error(rgbe_read_error,NULL);
+  }
+  if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == 0)
+    return rgbe_error(rgbe_read_error,NULL);
+  if (strcmp(buf,"\n") != 0)
+    return rgbe_error(rgbe_format_error,
+                     "missing blank line after FORMAT specifier");
+  if (fgets(buf,sizeof(buf)/sizeof(buf[0]),fp) == 0)
+    return rgbe_error(rgbe_read_error,NULL);
+  if (sscanf(buf,"-Y %d +X %d",height,width) < 2)
+    return rgbe_error(rgbe_format_error,"missing image size specifier");
+  return RGBE_RETURN_SUCCESS;
+}
+
+/* simple write routine that does not use run length encoding */
+/* These routines can be made faster by allocating a larger buffer and
+   fread-ing and fwrite-ing the data in larger chunks */
+int RGBE_WritePixels(FILE *fp, float *data, int numpixels)
+{
+  unsigned char rgbe[4];
+
+  while (numpixels-- > 0) {
+    float2rgbe(rgbe,data[RGBE_DATA_RED],
+              data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]);
+    data += RGBE_DATA_SIZE;
+    if (fwrite(rgbe, sizeof(rgbe), 1, fp) < 1)
+      return rgbe_error(rgbe_write_error,NULL);
+  }
+  return RGBE_RETURN_SUCCESS;
+}
+
+/* simple read routine.  will not correctly handle run length encoding */
+int RGBE_ReadPixels(FILE *fp, float *data, int numpixels)
+{
+  unsigned char rgbe[4];
+
+  while(numpixels-- > 0) {
+    if (fread(rgbe, sizeof(rgbe), 1, fp) < 1)
+      return rgbe_error(rgbe_read_error,NULL);
+    rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],
+              &data[RGBE_DATA_BLUE],rgbe);
+    data += RGBE_DATA_SIZE;
+  }
+  return RGBE_RETURN_SUCCESS;
+}
+
+/* The code below is only needed for the run-length encoded files. */
+/* Run length encoding adds considerable complexity but does */
+/* save some space.  For each scanline, each channel (r,g,b,e) is */
+/* encoded separately for better compression. */
+
+static int RGBE_WriteBytes_RLE(FILE *fp, unsigned char *data, int numbytes)
+{
+#define MINRUNLENGTH 4
+  int cur, beg_run, run_count, old_run_count, nonrun_count;
+  unsigned char buf[2];
+
+  cur = 0;
+  while(cur < numbytes) {
+    beg_run = cur;
+    /* find next run of length at least 4 if one exists */
+    run_count = old_run_count = 0;
+    while((run_count < MINRUNLENGTH) && (beg_run < numbytes)) {
+      beg_run += run_count;
+      old_run_count = run_count;
+      run_count = 1;
+      while( (beg_run + run_count < numbytes) && (run_count < 127)
+             && (data[beg_run] == data[beg_run + run_count]))
+       run_count++;
+    }
+    /* if data before next big run is a short run then write it as such */
+    if ((old_run_count > 1)&&(old_run_count == beg_run - cur)) {
+      buf[0] = 128 + old_run_count;   /*write short run*/
+      buf[1] = data[cur];
+      if (fwrite(buf,sizeof(buf[0])*2,1,fp) < 1)
+       return rgbe_error(rgbe_write_error,NULL);
+      cur = beg_run;
+    }
+    /* write out bytes until we reach the start of the next run */
+    while(cur < beg_run) {
+      nonrun_count = beg_run - cur;
+      if (nonrun_count > 128) 
+       nonrun_count = 128;
+      buf[0] = nonrun_count;
+      if (fwrite(buf,sizeof(buf[0]),1,fp) < 1)
+       return rgbe_error(rgbe_write_error,NULL);
+      if (fwrite(&data[cur],sizeof(data[0])*nonrun_count,1,fp) < 1)
+       return rgbe_error(rgbe_write_error,NULL);
+      cur += nonrun_count;
+    }
+    /* write out next run if one was found */
+    if (run_count >= MINRUNLENGTH) {
+      buf[0] = 128 + run_count;
+      buf[1] = data[beg_run];
+      if (fwrite(buf,sizeof(buf[0])*2,1,fp) < 1)
+       return rgbe_error(rgbe_write_error,NULL);
+      cur += run_count;
+    }
+  }
+  return RGBE_RETURN_SUCCESS;
+#undef MINRUNLENGTH
+}
+
+int RGBE_WritePixels_RLE(FILE *fp, float *data, int scanline_width,
+                        int num_scanlines)
+{
+  unsigned char rgbe[4];
+  unsigned char *buffer;
+  int i, err;
+
+  if ((scanline_width < 8)||(scanline_width > 0x7fff))
+    /* run length encoding is not allowed so write flat*/
+    return RGBE_WritePixels(fp,data,scanline_width*num_scanlines);
+  buffer = (unsigned char *)malloc(sizeof(unsigned char)*4*scanline_width);
+  if (buffer == NULL) 
+    /* no buffer space so write flat */
+    return RGBE_WritePixels(fp,data,scanline_width*num_scanlines);
+  while(num_scanlines-- > 0) {
+    rgbe[0] = 2;
+    rgbe[1] = 2;
+    rgbe[2] = scanline_width >> 8;
+    rgbe[3] = scanline_width & 0xFF;
+    if (fwrite(rgbe, sizeof(rgbe), 1, fp) < 1) {
+      free(buffer);
+      return rgbe_error(rgbe_write_error,NULL);
+    }
+    for(i=0;i<scanline_width;i++) {
+      float2rgbe(rgbe,data[RGBE_DATA_RED],
+                data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]);
+      buffer[i] = rgbe[0];
+      buffer[i+scanline_width] = rgbe[1];
+      buffer[i+2*scanline_width] = rgbe[2];
+      buffer[i+3*scanline_width] = rgbe[3];
+      data += RGBE_DATA_SIZE;
+    }
+    /* write out each of the four channels separately run length encoded */
+    /* first red, then green, then blue, then exponent */
+    for(i=0;i<4;i++) {
+      if ((err = RGBE_WriteBytes_RLE(fp,&buffer[i*scanline_width],
+                                    scanline_width)) != RGBE_RETURN_SUCCESS) {
+       free(buffer);
+       return err;
+      }
+    }
+  }
+  free(buffer);
+  return RGBE_RETURN_SUCCESS;
+}
+      
+int RGBE_ReadPixels_RLE(FILE *fp, float *data, int scanline_width,
+                       int num_scanlines)
+{
+  unsigned char rgbe[4], *scanline_buffer, *ptr, *ptr_end;
+  int i, count;
+  unsigned char buf[2];
+
+  if ((scanline_width < 8)||(scanline_width > 0x7fff))
+    /* run length encoding is not allowed so read flat*/
+    return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines);
+  scanline_buffer = NULL;
+  /* read in each successive scanline */
+  while(num_scanlines > 0) {
+    if (fread(rgbe,sizeof(rgbe),1,fp) < 1) {
+      free(scanline_buffer);
+      return rgbe_error(rgbe_read_error,NULL);
+    }
+    if ((rgbe[0] != 2)||(rgbe[1] != 2)||(rgbe[2] & 0x80)) {
+      /* this file is not run length encoded */
+      rgbe2float(&data[0],&data[1],&data[2],rgbe);
+      data += RGBE_DATA_SIZE;
+      free(scanline_buffer);
+      return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines-1);
+    }
+    if ((((int)rgbe[2])<<8 | rgbe[3]) != scanline_width) {
+      free(scanline_buffer);
+      return rgbe_error(rgbe_format_error,"wrong scanline width");
+    }
+    if (scanline_buffer == NULL)
+      scanline_buffer = (unsigned char *)
+       malloc(sizeof(unsigned char)*4*scanline_width);
+    if (scanline_buffer == NULL) 
+      return rgbe_error(rgbe_memory_error,"unable to allocate buffer space");
+    
+    ptr = &scanline_buffer[0];
+    /* read each of the four channels for the scanline into the buffer */
+    for(i=0;i<4;i++) {
+      ptr_end = &scanline_buffer[(i+1)*scanline_width];
+      while(ptr < ptr_end) {
+       if (fread(buf,sizeof(buf[0])*2,1,fp) < 1) {
+         free(scanline_buffer);
+         return rgbe_error(rgbe_read_error,NULL);
+       }
+       if (buf[0] > 128) {
+         /* a run of the same value */
+         count = buf[0]-128;
+         if ((count == 0)||(count > ptr_end - ptr)) {
+           free(scanline_buffer);
+           return rgbe_error(rgbe_format_error,"bad scanline data");
+         }
+         while(count-- > 0)
+           *ptr++ = buf[1];
+       }
+       else {
+         /* a non-run */
+         count = buf[0];
+         if ((count == 0)||(count > ptr_end - ptr)) {
+           free(scanline_buffer);
+           return rgbe_error(rgbe_format_error,"bad scanline data");
+         }
+         *ptr++ = buf[1];
+         if (--count > 0) {
+           if (fread(ptr,sizeof(*ptr)*count,1,fp) < 1) {
+             free(scanline_buffer);
+             return rgbe_error(rgbe_read_error,NULL);
+           }
+           ptr += count;
+         }
+       }
+      }
+    }
+    /* now convert data from buffer into floats */
+    for(i=0;i<scanline_width;i++) {
+      rgbe[0] = scanline_buffer[i];
+      rgbe[1] = scanline_buffer[i+scanline_width];
+      rgbe[2] = scanline_buffer[i+2*scanline_width];
+      rgbe[3] = scanline_buffer[i+3*scanline_width];
+      rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],
+                &data[RGBE_DATA_BLUE],rgbe);
+      data += RGBE_DATA_SIZE;
+    }
+    num_scanlines--;
+  }
+  free(scanline_buffer);
+  return RGBE_RETURN_SUCCESS;
+}
+
diff --git a/modules/highgui/src/rgbe.hpp b/modules/highgui/src/rgbe.hpp
new file mode 100644 (file)
index 0000000..35df0a5
--- /dev/null
@@ -0,0 +1,92 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's 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.
+//
+//   * The name of the copyright holders may not 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 Intel Corporation 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.
+//
+//M*/
+
+#ifndef _RGBE_HDR_H_
+#define _RGBE_HDR_H_
+
+// posted to http://www.graphics.cornell.edu/~bjw/
+// written by Bruce Walter  (bjw@graphics.cornell.edu)  5/26/95
+// based on code written by Greg Ward
+
+#include <stdio.h>
+
+typedef struct {
+  int valid;            /* indicate which fields are valid */
+  char programtype[16]; /* listed at beginning of file to identify it 
+                         * after "#?".  defaults to "RGBE" */ 
+  float gamma;          /* image has already been gamma corrected with 
+                         * given gamma.  defaults to 1.0 (no correction) */
+  float exposure;       /* a value of 1.0 in an image corresponds to
+                        * <exposure> watts/steradian/m^2. 
+                        * defaults to 1.0 */
+} rgbe_header_info;
+
+/* flags indicating which fields in an rgbe_header_info are valid */
+#define RGBE_VALID_PROGRAMTYPE 0x01
+#define RGBE_VALID_GAMMA       0x02
+#define RGBE_VALID_EXPOSURE    0x04
+
+/* return codes for rgbe routines */
+#define RGBE_RETURN_SUCCESS 0
+#define RGBE_RETURN_FAILURE -1
+
+/* read or write headers */
+/* you may set rgbe_header_info to null if you want to */
+int RGBE_WriteHeader(FILE *fp, int width, int height, rgbe_header_info *info);
+int RGBE_ReadHeader(FILE *fp, int *width, int *height, rgbe_header_info *info);
+
+/* read or write pixels */
+/* can read or write pixels in chunks of any size including single pixels*/
+int RGBE_WritePixels(FILE *fp, float *data, int numpixels);
+int RGBE_ReadPixels(FILE *fp, float *data, int numpixels);
+
+/* read or write run length encoded files */
+/* must be called to read or write whole scanlines */
+int RGBE_WritePixels_RLE(FILE *fp, float *data, int scanline_width,
+                        int num_scanlines);
+int RGBE_ReadPixels_RLE(FILE *fp, float *data, int scanline_width,
+                       int num_scanlines);
+
+#endif/*_RGBE_HDR_H_*/
+
+
+
index 185b8dc..b05140c 100644 (file)
@@ -80,6 +80,8 @@ CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs,
                                                     float h = 3, float hColor = 3,
                                                     int templateWindowSize = 7, int searchWindowSize = 21);
 
+CV_EXPORTS_W void makeHDR(InputArrayOfArrays srcImgs, std::vector<float> expTimes, OutputArray dst);
+
 } // cv
 
 #endif
diff --git a/modules/photo/src/hdr_fusion.cpp b/modules/photo/src/hdr_fusion.cpp
new file mode 100644 (file)
index 0000000..ba0a4c9
--- /dev/null
@@ -0,0 +1,115 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's 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.
+//
+//   * The name of the copyright holders may not 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 Intel Corporation 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.
+//
+//M*/
+
+#include "opencv2/photo.hpp"
+#include "opencv2/imgproc.hpp"
+
+namespace cv
+{
+
+static void triangleWeights(float weights[])
+{
+       for(int i = 0; i < 128; i++) {
+               weights[i] = i + 1.0f;
+       }
+       for(int i = 128; i < 256; i++) {
+               weights[i] = 256.0f - i;
+       }
+}
+
+static void generateResponce(float responce[])
+{
+    for(int i = 0; i < 256; i++) {
+        responce[i] = log((float)i);
+    }
+    responce[0] = responce[1];
+}
+
+void makeHDR(InputArrayOfArrays _images, std::vector<float> exp_times, OutputArray _dst)
+{
+       std::vector<Mat> images;
+    _images.getMatVector(images);
+       if(images.empty()) {
+               printf("Need at least one vector image.");
+       }
+       if(images.size() != exp_times.size()) {
+               printf("Number of images and number of exposure times must be equal.");
+       }
+       int width = images[0].cols;
+       int height = images[0].rows;
+       for(size_t i = 0; i < images.size(); i++) {
+
+               if(images[i].cols != width || images[i].rows != height) {
+                       printf("Image dimensions must be equal.");
+               }
+               if(images[i].type() != CV_8UC3) {
+                       printf("Images must have CV_8UC3 type.");
+               }
+       }
+       _dst.create(images[0].size(), CV_32FC3);
+       Mat result = _dst.getMat();
+       float weights[256], responce[256];
+       triangleWeights(weights);
+       generateResponce(responce);
+
+       float *res_ptr = result.ptr<float>();
+       for(size_t pos = 0; pos < result.total(); pos++, res_ptr += 3) {
+
+               float sum[3] = {0, 0, 0};
+               float weight_sum = 0;
+               for(size_t im = 0; im < images.size(); im++) {
+
+                       uchar *img_ptr = images[im].ptr() + 3 * pos;
+                       float w = (weights[img_ptr[0]] + weights[img_ptr[1]] +
+                                      weights[img_ptr[2]]) / 3;
+                       weight_sum += w;
+                       for(int channel = 0; channel < 3; channel++) {
+                               sum[channel] += w * (responce[img_ptr[channel]] - log(exp_times[im]));
+                       }
+               }
+               for(int channel = 0; channel < 3; channel++) {
+                       res_ptr[channel] = exp(sum[channel] / weight_sum);
+               }
+       }
+}
+
+};
\ No newline at end of file