Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
alta
alta
Commits
1af38761
Commit
1af38761
authored
Feb 15, 2017
by
Laurent Belcour
Browse files
Merged branch wip-tinyexr into master
parents
63aa6840
55788034
Changes
23
Hide whitespace changes
Inline
Side-by-side
.gitmodules
0 → 100644
View file @
1af38761
[submodule "external/tinyexr"]
path = external/tinyexr
url = https://github.com/syoyo/tinyexr.git
SConstruct
View file @
1af38761
...
...
@@ -75,7 +75,7 @@ vars.Add('INSTALL_PREFIX', 'Parent installation directory',
vars
.
Add
(
'CXX'
,
'C++ compiler'
,
default
=
program_file_name
(
cxx_compilers
))
vars
.
Add
(
'CCFLAGS'
,
'Compiler
\'
s flags'
,
default
=
'-std=c++11 -g
-O2
-Wall'
)
default
=
'-std=c++11 -g -Wall'
)
vars
.
Add
(
'LINKFLAGS'
,
'Linker
\'
s flags'
,
default
=
''
)
vars
.
Add
(
'EIGEN_INC'
,
'Eigen include directory (mandatory)'
)
...
...
@@ -191,12 +191,17 @@ def library_available(env, pkgspec='', lib='', header='',
return
result
def
openexr_available
(
env
):
"""Return True if OpenEXR is available."""
return
library_available
(
env
,
pkgspec
=
'OpenEXR'
,
inc_var
=
'OPENEXR_INC'
,
lib_var
=
'OPENEXR_DIR'
,
lib
=
'OPENEXR_LIB'
,
header
=
'ImfRgbaFile.h'
)
"""Return True if OpenEXR is available."""
env
.
AppendUnique
(
CPPPATH
=
'#external'
)
conf
=
Configure
(
env
)
has_tinyexr
=
conf
.
CheckCXXHeader
(
'tinyexr/tinyexr.h'
)
conf
.
Finish
()
return
has_tinyexr
#return library_available(env, pkgspec='OpenEXR',
# inc_var='OPENEXR_INC',
# lib_var='OPENEXR_DIR',
# lib='OPENEXR_LIB',
# header='ImfRgbaFile.h')
def
CheckOpenMP
(
context
):
"""
...
...
documents/contacts.dox
View file @
1af38761
...
...
@@ -17,6 +17,6 @@ The following people have been involved in ALTA development:
</ul>
More information on the project are available on the
<a href="https://g
forge
.inria.fr/
projects
/alta
/
">
Gforge project webpage
</a>
<a href="https://g
itlab
.inria.fr/
alta
/alta">
Inria Gitlab project
</a>
.
*/
documents/install.dox
View file @
1af38761
...
...
@@ -5,7 +5,7 @@
To access the sources of ALTA, clone the public [Git][git] repository:
$ git clone https://g
forge
.inria.fr/
git/
alta/alta.git
$ git clone https://g
itlab
.inria.fr/alta/alta.git
## Dependencies
...
...
documents/mainpage.dox
View file @
1af38761
...
...
@@ -39,7 +39,7 @@ ALTA is free software available under the [Mozilla Public License,
version 2.0](http://mozilla.org/MPL/2.0/). The latest release, version
0.2, can be obtained from the Git repository:
$ git clone https://g
forge
.inria.fr/
git/
alta/alta.git
$ git clone https://g
itlab
.inria.fr/alta/alta.git
$ git checkout v0.2
See \ref install "the installation instruction" for more information.
...
...
tinyexr
@
46d5063d
Subproject commit 46d5063d69d0264ccb200c50ae26b03d64ccd85e
sources/core/args.h
View file @
1af38761
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2014, 2015 Universtie de Montreal
Copyright (C) 2013, 2014 Inria
Copyright (C) 2013, 2014
, 2017
Inria
This file is part of ALTA.
...
...
@@ -14,6 +14,7 @@
#include <string>
#include <sstream>
#include <map>
#include <initializer_list>
#include <cstdlib>
#include <iostream>
#include <cctype>
...
...
@@ -33,12 +34,20 @@ namespace alta {
*/
class
arguments
{
private:
typedef
std
::
pair
<
const
std
::
string
,
std
::
string
>
pair_type
;
public:
// functions
// Constructor and destructor
arguments
()
{
}
arguments
(
std
::
initializer_list
<
pair_type
>
lst
)
:
_map
(
lst
)
{
}
arguments
(
int
argc
,
char
**
const
argv
)
{
for
(
int
i
=
0
;
i
<
argc
;
++
i
)
...
...
sources/core/common.h
View file @
1af38761
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2014 CNRS
Copyright (C) 2013, 2014, 2015, 2016 Inria
Copyright (C) 2013, 2014, 2015, 2016
, 2017
Inria
This file is part of ALTA.
...
...
@@ -38,6 +38,8 @@
typedef
Eigen
::
VectorXd
vec
;
typedef
Eigen
::
Ref
<
vec
>
vecref
;
typedef
Eigen
::
Ref
<
const
vec
>
const_vecref
;
typedef
Eigen
::
Matrix
<
double
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
,
Eigen
::
RowMajor
>
RowMatrixXd
;
// Convenience functions.
static
inline
double
norm
(
const
vec
&
v
)
...
...
sources/core/data_storage.cpp
View file @
1af38761
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2013, 2014, 2015, 2016 Inria
Copyright (C) 2013, 2014, 2015, 2016
, 2017
Inria
This file is part of ALTA.
...
...
@@ -63,8 +63,8 @@ static bool cosine_correction(vecref v, unsigned int dimX, unsigned int dimY,
static
bool
within_bounds
(
const
vecref
v
,
const
vec
&
min
,
const
vec
&
max
)
{
return
(
v
.
array
()
<
min
.
array
()).
all
()
&&
(
v
.
array
()
>
max
.
array
()).
all
();
return
(
v
.
array
()
>=
min
.
array
()).
all
()
&&
(
v
.
array
()
<=
max
.
array
()).
all
();
}
// Return the 'ci_kind' value corresponding to VS_VALUE, an integer found in
...
...
@@ -115,7 +115,7 @@ static void read_confidence_interval(std::istream& input,
else
{
// Confidence interval data not provided in INPUT.
double
dt
=
args
.
get_
float
(
"dt"
,
0.1
f
);
double
dt
=
args
.
get_
double
(
"dt"
,
0.1
d
);
min_dt
=
-
dt
;
max_dt
=
dt
;
}
...
...
@@ -153,12 +153,9 @@ static void read_confidence_interval(std::istream& input,
}
alta
::
data
*
alta
::
load_data_from_text
(
std
::
istream
&
input
,
const
alta
::
arguments
&
header
)
const
alta
::
arguments
&
header
,
const
alta
::
arguments
&
args
)
{
// FIXME: Eventually reinstate support for extra arguments when loading a
// file.
static
alta
::
arguments
args
;
vec
min
,
max
;
vec
ymin
,
ymax
;
...
...
@@ -217,25 +214,26 @@ alta::data* alta::load_data_from_text(std::istream& input,
for
(
int
i
=
0
;
i
<
2
*
dim
.
second
;
i
++
)
content
.
push_back
(
0.
);
// If data is not in the interval of fit
// std::cout << " start = " << start << " rows = " << row_count
// << " size = " << content.size() << "\n";
Map
<
VectorXd
>
v
(
&
content
[
start
],
row_count
);
// Read the confidence interval data if available.
read_confidence_interval
(
linestream
,
v
,
kind
,
dim
.
first
,
dim
.
second
,
args
);
// Check if we need to filter out what we just read according to ARGS.
// TODO: Move filtering to a post-parsing operation on 'data'.
if
(
!
(
within_bounds
(
v
.
segment
(
0
,
dim
.
first
),
min
,
max
)
&&
within_bounds
(
v
.
segment
(
dim
.
first
,
dim
.
second
),
ymin
,
ymax
)))
continue
;
if
(
args
.
is_defined
(
"data-correct-cosine"
))
{
content
.
resize
(
start
);
}
else
if
(
args
.
is_defined
(
"data-correct-cosine"
))
{
if
(
!
cosine_correction
(
v
.
segment
(
0
,
dim
.
first
+
dim
.
second
),
dim
.
first
,
dim
.
second
,
in_param
))
cont
inue
;
cont
ent
.
resize
(
start
)
;
}
// Read the confidence interval data if available.
read_confidence_interval
(
linestream
,
v
,
kind
,
dim
.
first
,
dim
.
second
,
args
);
}
}
...
...
sources/core/data_storage.h
View file @
1af38761
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2013, 2014, 2015, 2016 Inria
Copyright (C) 2013, 2014, 2015, 2016
, 2017
Inria
This file is part of ALTA.
...
...
@@ -25,9 +25,12 @@ namespace alta
void
save_data_as_binary
(
std
::
ostream
&
out
,
const
alta
::
data
&
data
);
// Return the data read from INPUT in ALTA's native text format.
// Return the data read from INPUT in ALTA's native text format. Read
// extra parsing parameters from ARGS. XXX: ARGS is currently used for
// extra filtering, which should really happen elsewhere.
data
*
load_data_from_text
(
std
::
istream
&
input
,
const
alta
::
arguments
&
header
);
const
alta
::
arguments
&
header
,
const
alta
::
arguments
&
args
=
alta
::
arguments
());
// Return the data read from the binary-formatted stream IN.
data
*
load_data_from_binary
(
std
::
istream
&
in
,
const
alta
::
arguments
&
header
);
...
...
sources/core/params.cpp
View file @
1af38761
...
...
@@ -831,3 +831,21 @@ void params::print_input_params()
std
::
cout
<<
it
->
second
.
info
<<
std
::
endl
;
}
}
bool
params
::
is_above_hemisphere
(
double
*
const
invec
,
params
::
input
in_param_type
)
{
vec
input_in_cartesian
(
6
);
params
::
convert
(
invec
,
in_param_type
,
params
::
CARTESIAN
,
&
input_in_cartesian
[
0
]);
return
input_in_cartesian
[
2
]
>=
0.0
&&
input_in_cartesian
[
5
]
>=
0.0
;
}
sources/core/params.h
View file @
1af38761
...
...
@@ -415,6 +415,17 @@ class params
static
void
print_input_params
();
//! \brief Check whether or not a (light,view) configuration is above the hemisphere
//! \return true if both vectors (light and view) are above and false otherwise
//! \remark the function returns true also for grazing, tangential configuration
//! (i.e., where light dot normal == 0 or view dot normal == 0)
static
bool
is_above_hemisphere
(
double
*
invec
,
params
::
input
intype
);
static
bool
inline
is_below_hemisphere
(
double
*
invec
,
params
::
input
intype
)
{
return
!
is_above_hemisphere
(
invec
,
intype
);
}
};
/*! \brief A parameters object. Allow to define function object (either data
...
...
sources/core/plugins_manager.cpp
View file @
1af38761
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2014, 2015 CNRS
Copyright (C) 2013, 2014, 2015, 2016 Inria
Copyright (C) 2013, 2014, 2015, 2016
, 2017
Inria
This file is part of ALTA.
...
...
@@ -486,8 +486,7 @@ ptr<data> plugins_manager::load_data(const std::string& type, std::istream& inpu
if
(
header
[
"FORMAT"
]
==
"binary"
)
{
result
=
ptr
<
data
>
(
load_data_from_binary
(
input
,
header
));
}
else
{
// FIXME: ARGS is currently ignored.
result
=
ptr
<
data
>
(
load_data_from_text
(
input
,
header
));
result
=
ptr
<
data
>
(
load_data_from_text
(
input
,
header
,
args
));
}
}
else
...
...
sources/core/vertical_segment.cpp
View file @
1af38761
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2013, 2014, 2015, 2016 Inria
Copyright (C) 2013, 2014, 2015, 2016
, 2017
Inria
This file is part of ALTA.
...
...
@@ -108,41 +108,28 @@ void vertical_segment::get(int i, vec& x, vec& yl, vec& yu) const
// Make sure we have the lower and upper bounds of Y.
assert
(
confidence_interval_kind
()
==
ASYMMETRICAL_CONFIDENCE_INTERVAL
);
auto
matrix
=
matrix_view
();
auto
row
=
matrix_view
()
.
row
(
i
)
;
#ifdef DEBUG
assert
(
i
>=
0
&&
i
<
matrix
.
size
());
#endif
x
.
resize
(
_parameters
.
dimX
());
yl
.
resize
(
_parameters
.
dimY
())
;
yu
.
resize
(
_parameters
.
dimY
())
;
for
(
int
j
=
0
;
j
<
_parameters
.
dimX
();
++
j
)
{
x
[
j
]
=
matrix
(
i
,
j
);
}
for
(
int
j
=
0
;
j
<
_parameters
.
dimY
();
++
j
)
{
yl
[
j
]
=
matrix
(
i
,
_parameters
.
dimX
()
+
1
*
_parameters
.
dimY
()
+
j
);
yu
[
j
]
=
matrix
(
i
,
_parameters
.
dimX
()
+
2
*
_parameters
.
dimY
()
+
j
);
}
x
=
row
.
segment
(
0
,
_parameters
.
dimX
());
auto
y
=
row
.
segment
(
_parameters
.
dimX
(),
_parameters
.
dimY
());
yl
=
row
.
segment
(
_parameters
.
dimX
()
+
_parameters
.
dimY
(),
_parameters
.
dimY
());
yu
=
row
.
segment
(
_parameters
.
dimX
()
+
2
*
_parameters
.
dimY
(),
_parameters
.
dimY
());
}
void
vertical_segment
::
get
(
int
i
,
vec
&
yl
,
vec
&
yu
)
const
{
// Make sure we have the lower and upper bounds of Y.
assert
(
confidence_interval_kind
()
==
ASYMMETRICAL_CONFIDENCE_INTERVAL
);
auto
matrix
=
matrix_view
();
yl
.
resize
(
_parameters
.
dimY
())
;
yu
.
resize
(
_parameters
.
dimY
())
;
for
(
int
j
=
0
;
j
<
_parameters
.
dimY
();
++
j
)
{
yl
[
j
]
=
matrix
(
i
,
_parameters
.
dimX
()
+
_parameters
.
dimY
()
+
j
);
yu
[
j
]
=
matrix
(
i
,
_parameters
.
dimX
()
+
2
*
_parameters
.
dimY
()
+
j
);
}
vec
x
;
get
(
i
,
x
,
yl
,
yu
);
}
vec
vertical_segment
::
get
(
int
i
)
const
{
return
data_view
().
col
(
i
);
return
data_view
().
row
(
i
);
}
void
vertical_segment
::
set
(
int
i
,
const
vec
&
x
)
...
...
sources/core/vertical_segment.h
View file @
1af38761
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2013, 2014, 2015, 2016 Inria
Copyright (C) 2013, 2014, 2015, 2016
, 2017
Inria
This file is part of ALTA.
...
...
@@ -164,20 +164,19 @@ class vertical_segment : public data
// Thus, it has (dimX + dimY + N * dimY) columns, where N is between 0
// and 2 depending on the confidence interval data available, and SIZE
// rows.
Eigen
::
Map
<
Eigen
::
MatrixXd
>
matrix_view
()
const
Eigen
::
Map
<
Row
MatrixXd
>
matrix_view
()
const
{
return
Eigen
::
Map
<
Eigen
::
MatrixXd
>
(
_data
.
get
(),
size
(),
column_number
());
return
Eigen
::
Map
<
RowMatrixXd
>
(
_data
.
get
(),
size
(),
column_number
());
}
private:
// method
//! \brief Return a matrix view of DATA that excludes confidence
// interval data. It has (dimX + dimY) columns and SIZE rows.
Eigen
::
Map
<
Eigen
::
MatrixXd
,
0
,
Eigen
::
OuterStride
<>
>
data_view
()
const
Eigen
::
Map
<
Row
MatrixXd
,
0
,
Eigen
::
OuterStride
<>
>
data_view
()
const
{
return
Eigen
::
Map
<
Eigen
::
MatrixXd
,
0
,
Eigen
::
OuterStride
<>
>
(
_data
.
get
(),
_parameters
.
dimX
()
+
_parameters
.
dimY
(),
size
(),
return
Eigen
::
Map
<
Row
MatrixXd
,
0
,
Eigen
::
OuterStride
<>
>
(
_data
.
get
(),
_size
,
_parameters
.
dimX
()
+
_parameters
.
dimY
(),
Eigen
::
OuterStride
<>
(
column_number
()));
}
...
...
sources/plugins/data_io/EXR_IO.h
View file @
1af38761
#ifndef EXR_IO_H_
#define EXR_IO_H_
/*
* Author: Cyril Soler
*/
/* ALTA --- Analysis of Bidirectional Reflectance Distribution Functions
Copyright (C) 2017 Unity Technologies
This file is part of ALTA.
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once
// STL includes
#include <stdexcept>
#include <cassert>
#include <ImfRgbaFile.h>
#include <ImfArray.h>
// TinyEXR includes
#define TINYEXR_IMPLEMENTATION
#include <tinyexr/tinyexr.h>
// XXX: This header is not installed as of version 2.2.0 of OpenEXR, see
// <https://lists.nongnu.org/archive/html/openexr-devel/2016-06/msg00001.html>
// and <https://github.com/openexr/openexr/pull/184>.
#include <ImfStdIO.h>
/*! \class EXR_IO
*
* \details
* EXR_IO provides static method to either load an RGB EXR file into a floatting
* point array or save a RGB floatting point array to disk._data
*
* \author Laurent Belcour
*/
template
<
typename
FType
>
class
t_EXR_IO
{
public:
static
bool
LoadEXR
(
std
::
istream
&
input
,
int
&
W
,
int
&
H
,
FType
*&
pix
,
int
nC
=
3
)
/*! \brief Load an EXR file from an input file stream.
*/
static
bool
LoadEXR
(
std
::
istream
&
input
,
int
&
W
,
int
&
H
,
FType
*&
pix
,
int
nC
=
3
)
{
// XXX: OpenEXR implements its own IStream and OStream classes, but
// they are completely independent from those of libstdc++. The
// closest thing it has is 'StdIFStream', hence this hack.
std
::
ifstream
*
ifstream
=
dynamic_cast
<
std
::
ifstream
*>
(
&
input
);
assert
(
ifstream
!=
NULL
);
Imf
::
StdIFStream
iifstream
(
*
ifstream
,
"unknown file name"
);
Imf
::
RgbaInputFile
file
(
iifstream
);
Imath
::
Box2i
dw
=
file
.
dataWindow
();
W
=
dw
.
max
.
x
-
dw
.
min
.
x
+
1
;
H
=
dw
.
max
.
y
-
dw
.
min
.
y
+
1
;
Imf
::
Array2D
<
Imf
::
Rgba
>
pixels
;
pixels
.
resizeErase
(
H
,
W
);
file
.
setFrameBuffer
(
&
pixels
[
0
][
0
]
-
dw
.
min
.
x
-
dw
.
min
.
y
*
W
,
1
,
W
);
file
.
readPixels
(
dw
.
min
.
y
,
dw
.
max
.
y
);
pix
=
new
FType
[
W
*
H
*
3
]
;
switch
(
nC
)
{
case
3
:
for
(
int
i
=
0
;
i
<
H
;
++
i
)
for
(
int
j
=
0
;
j
<
W
;
++
j
)
{
pix
[
3
*
(
j
+
i
*
W
)
+
0
]
=
pixels
[
H
-
i
-
1
][
j
].
r
;
pix
[
3
*
(
j
+
i
*
W
)
+
1
]
=
pixels
[
H
-
i
-
1
][
j
].
g
;
pix
[
3
*
(
j
+
i
*
W
)
+
2
]
=
pixels
[
H
-
i
-
1
][
j
].
b
;
}
break
;
case
1
:
for
(
int
i
=
0
;
i
<
H
;
++
i
)
for
(
int
j
=
0
;
j
<
W
;
++
j
)
pix
[
j
+
i
*
W
]
=
0.3
*
pixels
[
H
-
i
-
1
][
j
].
r
+
0.59
*
pixels
[
H
-
i
-
1
][
j
].
g
+
0.11
*
pixels
[
H
-
i
-
1
][
j
].
b
;
break
;
default:
throw
std
::
runtime_error
(
"Unexpected case in EXR_IO."
)
;
/* Convert the input std::istream into an unsigned char array */
std
::
vector
<
unsigned
char
>
_memory
;
size_t
_n
=
0
,
_m
=
0
;
while
(
input
.
good
())
{
if
(
_n
==
_m
)
{
_m
+=
256
;
_memory
.
resize
(
_m
);
}
_memory
[
_n
++
]
=
(
unsigned
char
)
input
.
get
();
}
/* Check the different part of loading */
int
_r
=
-
1
;
const
char
*
_err
;
/* Load the EXR version using TinyEXR */
EXRVersion
_version
;
_r
=
ParseEXRVersionFromMemory
(
&
_version
,
&
_memory
[
0
]);
if
(
_r
!=
TINYEXR_SUCCESS
)
{
std
::
cerr
<<
"<<ERROR>> Could not load EXR version from stream"
<<
std
::
endl
;
return
false
;
}
else
{
std
::
cout
<<
"<<DEBUG>> Loading a v"
<<
_version
.
version
<<
" EXR file"
<<
std
::
endl
;
}
/* Load the EXR header */
EXRHeader
_header
;
InitEXRHeader
(
&
_header
);
_r
=
ParseEXRHeaderFromMemory
(
&
_header
,
&
_version
,
&
_memory
[
0
],
&
_err
);
if
(
_r
!=
TINYEXR_SUCCESS
)
{
std
::
cerr
<<
"<<ERROR>> Could not load EXR header from stream"
<<
std
::
endl
;
std
::
cerr
<<
"<<ERROR>> "
<<
_err
<<
std
::
endl
;
return
false
;
}
else
{
std
::
cout
<<
"<<DEBUG>> Loading a "
<<
_header
.
num_channels
<<
" channels EXR file"
<<
std
::
endl
;
}
/* Set the requested pixel types */
for
(
int
i
=
0
;
i
<
_header
.
num_channels
;
++
i
)
{
_header
.
requested_pixel_types
[
i
]
=
TINYEXR_PIXELTYPE_FLOAT
;
}
/* Load the EXR image */
EXRImage
_image
;
InitEXRImage
(
&
_image
);
_r
=
LoadEXRImageFromMemory
(
&
_image
,
&
_header
,
&
_memory
[
0
],
&
_err
);
if
(
_r
!=
TINYEXR_SUCCESS
)
{
std
::
cerr
<<
"<<ERROR>> Could not load EXR image from stream"
<<
std
::
endl
;
std
::
cerr
<<
"<<ERROR>> "
<<
_err
<<
std
::
endl
;
return
false
;
}
else
{
std
::
cout
<<
"<<DEBUG>> Loading a "
<<
_image
.
width
<<
"x"
<<
_image
.
height
<<
" EXR file"
<<
std
::
endl
;
}
/*! \todo Check the different channels if they match RGB */
/*! \todo handle VS data using multi-channel */
/* Recopy the image into the provided pixel array */
W
=
_image
.
width
;
H
=
_image
.
height
;
pix
=
new
FType
[
W
*
H
*
3
];
for
(
int
k
=
0
;
k
<
_image
.
num_channels
;
++
k
)
{
for
(
int
i
=
0
;
i
<
W
*
H
;
++
i
)
{
const
FType
val
=
(
FType
)(
reinterpret_cast
<
float
**>
(
_image
.
images
)[
k
][
i
]);
switch
(
_header
.
channels
[
k
].
name
[
0
])
{
case
'R'
:
pix
[
3
*
i
+
0
]
=
val
;
break
;
case
'G'
:
pix
[
3
*
i
+
1
]
=
val
;
break
;
case
'B'
:
pix
[
3
*
i
+
2
]
=
val
;
break
;
default:
std
::
cout
<<
"<<DEBUG>> Unknow EXR channel
\'
"
<<
_header
.
channels
[
k
].
name
[
0
]
<<
"
\'
"
<<
std
::
endl
;
}
}
}
/* Free TinyEXR memory */
_r
=
FreeEXRHeader
(
&
_header
);
_r
=
FreeEXRImage
(
&
_image
);
return
true
;
}
/*! \brief Save a RGB image into and OpenEXR file using TinyEXR.
* This code uses TinyEXR's reference implementation of saving a file as
* we do not manipulate streams here.
*/
static
bool
SaveEXR
(
const
char
*
filename
,
int
W
,
int
H
,
const
FType
*
pix
,
int
nC
=
3
)
{
Imf
::
Array2D
<
Imf
::
Rgba
>
pixels
(
H
,
W
);
/* Convert separated channel representation to per pixel representation */
switch
(
nC
)
{
case
3
:
for
(
int
row
=
0
;
row
<
H
;
row
++
)
for
(
int
i
=
0
;
i
<
W
;
i
++
)
{
Imf
::
Rgba
&
p
=
pixels
[
H
-
row
-
1
][
i
];
p
.
r
=
pix
[
3
*
(
i
+
row
*
W
)
+
0
]
;
p
.
g
=
pix
[
3
*
(
i
+
row
*
W
)
+
1
]
;
p
.
b
=
pix
[
3
*
(
i
+
row
*
W
)
+
2
]
;
p
.
a
=
1.0
;
}
break
;
case
1
:
for
(
int
row
=
0
;
row
<
H
;
row
++
)
for
(
int
i
=
0
;
i
<
W
;
i
++
)
{
Imf
::
Rgba
&
p
=
pixels
[
H
-
row
-
1
][
i
];
p
.
r
=
pix
[
i
+
row
*
W
]
;
p
.
g
=
pix
[
i
+
row
*
W
]
;
p
.
b
=
pix
[
i
+
row
*
W
]
;
p
.
a
=
FType
(
1.0
)
;
}
break
;
default:
throw
std
::
runtime_error
(
"Unexpected case in EXR_IO."
)
;
EXRHeader
header
;
InitEXRHeader
(
&
header
);
EXRImage
image
;
InitEXRImage
(
&
image
);
image
.
num_channels
=
3
;