Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Olena
pylene
Commits
ecb47cac
Commit
ecb47cac
authored
Jan 22, 2019
by
Michaël Roynard
Committed by
Edwin Carlinet
Jan 22, 2019
Browse files
zip view (PR4)
parent
e9730905
Changes
13
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
ecb47cac
...
...
@@ -8,4 +8,6 @@
.vs
.idea
*.pyc
/venv_*/
\ No newline at end of file
compile_commands.json
/venv_*/
/**/.DS_Store
\ No newline at end of file
.vscode/settings.json
View file @
ecb47cac
...
...
@@ -60,6 +60,7 @@
"queue"
:
"cpp"
,
"stack"
:
"cpp"
},
"python.pythonPath"
:
"/usr/bin/python3"
,
"C_Cpp.configurationWarnings"
:
"Disabled"
"python.pythonPath"
:
"venv_python37/bin/python"
,
"C_Cpp.configurationWarnings"
:
"Disabled"
,
"git.ignoreLimitWarning"
:
true
}
\ No newline at end of file
pylene/include/mln/core/image/private/image_operators.hpp
View file @
ecb47cac
...
...
@@ -2,6 +2,7 @@
#include <functional>
#include <mln/core/image/view/transform.hpp>
#include <mln/core/image/view/zip.hpp>
#include <mln/core/rangev3/foreach.hpp>
namespace
mln
::
experimental
...
...
@@ -97,14 +98,13 @@ namespace mln::experimental
template
<
class
ICond
,
class
ITrue
,
class
IFalse
>
struct
where_fn
<
ICond
,
ITrue
,
IFalse
,
std
::
enable_if_t
<
is_a
<
ITrue
,
Image
>::
value
&&
is_a
<
IFalse
,
Image
>::
value
>>
{
auto
operator
()(
const
ICond
&
/*
cond
*/
,
ITrue
/*
iftrue
*/
,
IFalse
/*
iffalse
*/
)
const
auto
operator
()(
const
ICond
&
cond
,
ITrue
iftrue
,
IFalse
iffalse
)
const
{
auto
g
=
[](
bool
vcond
,
auto
&&
vtrue
,
auto
&&
vfalse
)
->
decltype
(
auto
)
{
return
(
vcond
)
?
std
::
forward
<
decltype
(
vtrue
)
>
(
vtrue
)
:
std
::
forward
<
decltype
(
vfalse
)
>
(
vfalse
);
auto
g
=
[](
auto
tuple_ternary_expr
)
->
decltype
(
auto
)
{
return
(
std
::
get
<
0
>
(
tuple_ternary_expr
))
?
std
::
get
<
1
>
(
tuple_ternary_expr
)
:
std
::
get
<
2
>
(
tuple_ternary_expr
);
};
// FIXME: to be implemented with imzip
return
;
return
view
::
transform
(
view
::
zip
(
cond
,
iftrue
,
iffalse
),
g
);
}
};
...
...
@@ -144,42 +144,42 @@ namespace mln::experimental
return
view
::
transform
(
cond
,
g
);
}
};
}
// namespace details
}
// namespace details
template
<
class
ICond
,
class
ITrue
,
class
IFalse
>
auto
where
(
const
Image
<
ICond
>&
cond
,
ITrue
iftrue
,
IFalse
iffalse
)
{
return
details
::
where_fn
<
ICond
,
ITrue
,
IFalse
>
()(
static_cast
<
const
ICond
&>
(
cond
),
std
::
move
(
iftrue
),
std
::
move
(
iffalse
));
}
template
<
class
ICond
,
class
ITrue
,
class
IFalse
>
auto
where
(
const
Image
<
ICond
>&
cond
,
ITrue
iftrue
,
IFalse
iffalse
)
{
return
details
::
where_fn
<
ICond
,
ITrue
,
IFalse
>
()(
static_cast
<
const
ICond
&>
(
cond
),
std
::
move
(
iftrue
),
std
::
move
(
iffalse
));
}
// FIXME: deprecated => replace with algorithm all_of
template
<
class
I
>
[[
deprecated
]]
bool
all
(
I
ima
)
{
static_assert
(
mln
::
is_a
<
I
,
Image
>
());
static_assert
(
std
::
is_convertible
<
typename
I
::
reference
,
bool
>
());
// FIXME: deprecated => replace with algorithm all_of
template
<
class
I
>
[[
deprecated
]]
bool
all
(
I
ima
)
{
static_assert
(
mln
::
is_a
<
I
,
Image
>
());
static_assert
(
std
::
is_convertible
<
typename
I
::
reference
,
bool
>
());
mln_foreach_new
(
auto
&&
val
,
ima
.
new_values
())
if
(
!
val
)
return
false
;
mln_foreach_new
(
auto
&&
val
,
ima
.
new_values
())
if
(
!
val
)
return
false
;
return
true
;
}
return
true
;
}
template
<
class
I
>
[[
deprecated
]]
bool
any
(
I
ima
)
{
static_assert
(
mln
::
is_a
<
I
,
Image
>
());
static_assert
(
std
::
is_convertible
<
typename
I
::
reference
,
bool
>
());
template
<
class
I
>
[[
deprecated
]]
bool
any
(
I
ima
)
{
static_assert
(
mln
::
is_a
<
I
,
Image
>
());
static_assert
(
std
::
is_convertible
<
typename
I
::
reference
,
bool
>
());
mln_foreach_new
(
auto
&&
val
,
ima
.
new_values
())
if
(
val
)
return
true
;
mln_foreach_new
(
auto
&&
val
,
ima
.
new_values
())
if
(
val
)
return
true
;
return
false
;
}
return
false
;
}
#undef MLN_PRIVATE_DEFINE_UNARY_OPERATOR
...
...
pylene/include/mln/core/image/view/adaptor.hpp
View file @
ecb47cac
...
...
@@ -208,8 +208,8 @@ namespace mln
return
m_ima
.
index_of_point
(
p
);
}
template
<
typename
dummy
=
I
,
typename
=
std
::
enable_if_t
<
(
indexable
::
value
&&
accessible
::
value
)>
>
point_type
point_at_index
(
image_index_t
<
dummy
>
i
)
const
template
<
typename
dummy
=
I
>
point_type
point_at_index
(
std
::
enable_if_t
<
(
indexable
::
value
&&
accessible
::
value
),
image_index_t
<
dummy
>
>
i
)
const
{
return
m_ima
.
point_at_index
(
i
);
}
...
...
pylene/include/mln/core/image/view/transform.hpp
View file @
ecb47cac
...
...
@@ -27,12 +27,6 @@ namespace mln
static_assert
(
!
(
std
::
is_rvalue_reference_v
<
reference
>
&&
!
std
::
is_reference_v
<
image_reference_t
<
I
>>
),
"The transformed image returns a temporary and the mapping function is a projection.
\n
"
"This is building a dangling reference."
);
using
concrete_type
=
image_ch_value_t
<
I
,
value_type
>
;
template
<
typename
V
>
using
ch_value_type
=
image_ch_value_t
<
I
,
V
>
;
/// \}
...
...
@@ -45,13 +39,15 @@ namespace mln
// Transform doesn't preserve contiguity, so it decays from raw_image_tag
using
category_type
=
std
::
conditional_t
<
std
::
is_base_of_v
<
raw_image_tag
,
image_category_t
<
I
>>
,
bidirectional_image_tag
,
image_category_t
<
I
>>
;
/// \}
using
concrete_type
=
image_ch_value_t
<
I
,
value_type
>
;
private:
// FIXME may be a simpler way ?
// note that pixels() can return a proxy convertible to the pixel_type ? Or does it?
// using pixel_range_base_type = decltype(std::declval<I&>.pixels());
// using pixel_proxy_base_type = ::ranges::range_value_t<pixel_proxy_base_type>;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template
<
concepts
::
Value
V
>
#else
template
<
typename
V
>
#endif
using
ch_value_type
=
image_ch_value_t
<
I
,
V
>
;
/// \}
public:
/// Pixel type definitions
...
...
@@ -182,7 +178,8 @@ namespace mln
template
<
class
I1
,
class
I2
,
class
F
>
class
transform2_view
:
public
experimental
::
Image
<
transform2_view
<
I1
,
I2
,
F
>>
{
using
fun_t
=
F
;
using
fun_t
=
F
;
using
common_category
=
std
::
common_type_t
<
image_category_t
<
I1
>
,
image_category_t
<
I2
>>
;
I1
m_ima1
;
I2
m_ima2
;
fun_t
fun_
;
...
...
@@ -191,28 +188,34 @@ namespace mln
/// Type definitions
/// \{
using
reference
=
std
::
invoke_result_t
<
F
&
,
typename
I1
::
reference
,
typename
I2
::
reference
>
;
using
value_type
=
std
::
decay
_t
<
reference
>
;
using
point_type
=
typename
I1
::
point_t
ype
;
using
domain_type
=
typename
I1
::
domain_t
ype
;
using
value_type
=
std
::
remove_cv_t
<
std
::
remove_reference
_t
<
reference
>
>
;
using
point_type
=
std
::
common_type_t
<
image_point_t
<
I1
>
,
image_
point_t
<
I2
>>
;
using
domain_type
=
std
::
common_type_t
<
image_domain_t
<
I1
>
,
image_
domain_t
<
I2
>>
;
/// \}
/// Traits & Image Properties
/// \{
using
accessible
=
std
::
bool_constant
<
I1
::
accessible
::
value
&&
I2
::
accessible
::
value
>
;
using
indexable
=
std
::
false_type
;
// Preservative behavior
using
indexable
=
std
::
false_type
;
// Preservative behavior
using
view
=
std
::
true_type
;
using
extension_category
=
mln
::
extension
::
none_extension_tag
;
// Preservative behavior (may be too preservative)
// Transform doesn't preserve contiguity, so it decays from raw_image_tag
using
category_type
=
std
::
conditional_t
<
std
::
is_base_of_v
<
raw_image_tag
,
common_category
>
,
bidirectional_image_tag
,
common_category
>
;
using
concrete_type
=
std
::
common_type_t
<
image_ch_value_t
<
I1
,
value_type
>
,
image_ch_value_t
<
I2
,
value_type
>>
;
using
concrete_type
=
image_ch_value_t
<
I1
,
value_type
>
;
template
<
class
V
>
using
ch_value_type
=
image_ch_value_t
<
I1
,
V
>
;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template
<
concepts
::
Value
V
>
#else
template
<
typename
V
>
#endif
using
ch_value_type
=
std
::
common_type_t
<
image_ch_value_t
<
I1
,
V
>
,
image_ch_value_t
<
I2
,
V
>>
;
/// \}
public:
/// Pixel type definitions
/// \{
struct
new_pixel_type
:
pixel_adaptor
<
image_pixel_t
<
I1
>>
,
Pixel
<
new_pixel_type
>
struct
new_pixel_type
:
Pixel
<
new_pixel_type
>
{
public:
using
point_type
=
transform2_view
::
point_type
;
...
...
@@ -222,36 +225,27 @@ namespace mln
new_pixel_type
(
fun_t
fun
,
image_pixel_t
<
I1
>
px1
,
image_pixel_t
<
I2
>
px2
)
:
new
_pix
el_type
::
pixel_adaptor
{
std
::
move
(
px1
)}
:
m
_pix
1
{
std
::
move
(
px1
)}
,
m_pix2
{
std
::
move
(
px2
)}
,
fun_
{
std
::
move
(
fun
)}
{
}
new_pixel_type
(
const
new_pixel_type
&
other
)
:
new_pixel_type
::
pixel_adaptor
{
other
}
,
m_pix2
{
other
.
m_pix2
}
,
fun_
(
other
.
fun_
)
{
}
new_pixel_type
(
new_pixel_type
&&
other
)
:
new_pixel_type
::
pixel_adaptor
{
std
::
move
(
other
)}
,
m_pix2
{
std
::
move
(
other
.
m_pix2
)}
,
fun_
(
std
::
move
(
other
.
fun_
))
{
}
new_pixel_type
(
const
new_pixel_type
&
other
)
=
default
;
new_pixel_type
(
new_pixel_type
&&
other
)
=
default
;
reference
val
()
const
{
return
std
::
invoke
(
fun_
,
new
_pix
el_type
::
pixel_adaptor
::
val
(),
m_pix2
.
val
());
}
auto
point
()
const
{
return
new
_pix
el_type
::
pixel_adaptor
::
point
();
}
reference
val
()
const
{
return
std
::
invoke
(
fun_
,
m
_pix
1
.
val
(),
m_pix2
.
val
());
}
auto
point
()
const
{
return
m
_pix
1
.
point
();
}
void
advance
(
point_type
p
)
{
new
_pix
el_type
::
pixel_adaptor
::
advance
(
p
);
m
_pix
1
.
advance
(
p
);
m_pix2
.
advance
(
p
);
}
private:
fun_t
fun_
;
image_pixel_t
<
I1
>
m_pix1
;
image_pixel_t
<
I2
>
m_pix2
;
fun_t
fun_
;
};
/// \}
...
...
@@ -262,69 +256,72 @@ namespace mln
{
}
transform2_view
(
const
transform2_view
&
other
)
:
m_ima1
(
other
.
m_ima1
)
,
m_ima2
(
other
.
m_ima2
)
/*transform_view::image_adaptor{other}*/
,
fun_
(
other
.
fun_
)
{
}
transform2_view
(
transform2_view
&&
other
)
:
m_ima1
(
std
::
move
(
other
.
m_ima1
))
,
m_ima2
(
std
::
move
(
other
.
m_ima2
))
/*transform_view::image_adaptor{std::move(other)}*/
,
fun_
(
std
::
move
(
other
.
fun_
))
{
}
transform2_view
(
const
transform2_view
&
other
)
=
default
;
transform2_view
(
transform2_view
&&
other
)
=
default
;
decltype
(
auto
)
concretize
()
const
{
return
i
mchvalue
<
value_type
>
(
this
->
base
()
);
}
decltype
(
auto
)
concretize
()
const
{
return
m
_ima1
.
template
ch
_
value
<
value_type
>();
}
;
template
<
class
U
>
template
<
class
V
>
decltype
(
auto
)
ch_value
()
const
{
return
i
mchvalue
<
U
>
(
this
->
base
()
);
return
m
_ima1
.
template
ch
_
value
<
V
>(
);
}
auto
domain
()
const
{
return
m_ima1
.
domain
();
}
auto
new_values
()
{
return
mln
::
ranges
::
view
::
transform
(
m_ima1
.
new_values
(),
m_ima2
.
new_values
(),
fun_
);
}
auto
new_values
()
{
static_assert
(
::
ranges
::
ForwardRange
<
decltype
(
m_ima1
.
new_values
())
>
());
static_assert
(
::
ranges
::
ForwardRange
<
decltype
(
m_ima2
.
new_values
())
>
());
return
mln
::
ranges
::
view
::
transform
(
m_ima1
.
new_values
(),
m_ima2
.
new_values
(),
fun_
);
}
auto
new_pixels
()
{
using
R1
=
decltype
(
m_ima1
.
new_pixels
());
using
R2
=
decltype
(
m_ima2
.
new_pixels
());
using
R1
=
decltype
(
m_ima1
.
new_pixels
());
using
R2
=
decltype
(
m_ima2
.
new_pixels
());
static_assert
(
::
ranges
::
ForwardRange
<
R1
>
());
static_assert
(
::
ranges
::
ForwardRange
<
R2
>
());
auto
pxwrapper
=
[
fun
=
this
->
fun_
](
::
ranges
::
range_reference_t
<
R1
>
px1
,
::
ranges
::
range_reference_t
<
R2
>
px2
)
{
return
new_pixel_type
{
fun
,
std
::
move
(
px1
),
std
::
move
(
px2
)};
};
return
mln
::
ranges
::
view
::
transform
(
m_ima1
.
new_pixels
(),
m_ima2
.
new_pixels
(),
pxwrapper
);
}
template
<
typename
dummy
=
reference
>
std
::
enable_if_t
<
accessible
::
value
,
dummy
>
operator
()(
point_type
p
)
/// Accessible-image related methods
/// \{
template
<
typename
Ret
=
reference
>
std
::
enable_if_t
<
accessible
::
value
,
Ret
>
operator
()(
point_type
p
)
{
mln_precondition
(
m_ima1
.
domain
().
has
(
p
));
mln_precondition
(
m_ima2
.
domain
().
has
(
p
));
return
std
::
invoke
(
fun_
,
m_ima1
.
at
(
p
),
m_ima2
.
at
(
p
));
}
template
<
typename
dummy
=
reference
>
std
::
enable_if_t
<
accessible
::
value
,
dummy
>
at
(
point_type
p
)
template
<
typename
Ret
=
reference
>
std
::
enable_if_t
<
accessible
::
value
,
Ret
>
at
(
point_type
p
)
{
return
std
::
invoke
(
fun_
,
m_ima1
.
at
(
p
),
m_ima2
.
at
(
p
));
}
template
<
typename
dummy
=
new_pixel_type
>
std
::
enable_if_t
<
accessible
::
value
,
dummy
>
new_pixel
(
point_type
p
)
template
<
typename
Ret
=
new_pixel_type
>
std
::
enable_if_t
<
accessible
::
value
,
Ret
>
new_pixel
(
point_type
p
)
{
mln_precondition
(
m_ima1
.
domain
().
has
(
p
));
mln_precondition
(
m_ima2
.
domain
().
has
(
p
));
return
{
fun_
,
m_ima1
.
new_pixel
(
p
),
m_ima2
.
new_pixel
(
p
)};
}
template
<
typename
dummy
=
new_pixel_type
>
std
::
enable_if_t
<
accessible
::
value
,
dummy
>
new_pixel_at
(
point_type
p
)
template
<
typename
Ret
=
new_pixel_type
>
std
::
enable_if_t
<
accessible
::
value
,
Ret
>
new_pixel_at
(
point_type
p
)
{
return
{
fun_
,
m_ima1
.
new_pixel_at
(
p
),
m_ima2
.
new_pixel_at
(
p
)};
}
/// \}
};
...
...
@@ -345,6 +342,11 @@ namespace mln
static_assert
(
mln
::
is_a
<
I1
,
experimental
::
Image
>
());
static_assert
(
mln
::
is_a
<
I2
,
experimental
::
Image
>
());
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert
(
mln
::
concepts
::
InputImage
<
I1
>
);
static_assert
(
mln
::
concepts
::
InputImage
<
I2
>
);
#endif
return
{
std
::
move
(
ima1
),
std
::
move
(
ima2
),
std
::
move
(
fun
)};
}
}
// namespace view
...
...
pylene/include/mln/core/image/view/zip.hpp
0 → 100644
View file @
ecb47cac
#pragma once
#include <mln/core/image/image.hpp>
#include <mln/core/image/view/adaptor.hpp>
#include <mln/core/rangev3/view/zip.hpp>
#include <tuple>
#include <type_traits>
namespace
mln
{
template
<
class
...
Images
>
class
zip_view
:
public
experimental
::
Image
<
zip_view
<
Images
...
>>
{
using
tuple_t
=
std
::
tuple
<
Images
...
>
;
using
I0
=
typename
std
::
tuple_element
<
0
,
tuple_t
>::
type
;
using
common_category
=
std
::
common_type_t
<
image_category_t
<
Images
>
...
>
;
tuple_t
m_images
;
public:
/// Type definitions
/// \{
using
reference
=
std
::
tuple
<
image_reference_t
<
Images
>
...
>
;
using
value_type
=
std
::
tuple
<
image_value_t
<
Images
>
...
>
;
using
point_type
=
std
::
common_type_t
<
image_point_t
<
Images
>
...
>
;
using
domain_type
=
std
::
common_type_t
<
image_domain_t
<
Images
>
...
>
;
/// \}
/// Traits & Image Properties
/// \{
using
accessible
=
std
::
conjunction
<
typename
Images
::
accessible
...
>
;
using
indexable
=
std
::
false_type
;
// Preservative behavior
using
view
=
std
::
true_type
;
using
extension_category
=
mln
::
extension
::
none_extension_tag
;
// Preservative behavior
// Zip doesn't preserve contiguity, so it decays from raw_image_tag
using
category_type
=
std
::
conditional_t
<
std
::
is_base_of_v
<
raw_image_tag
,
common_category
>
,
bidirectional_image_tag
,
common_category
>
;
using
concrete_type
=
image_ch_value_t
<
I0
,
typename
I0
::
value_type
>
;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template
<
concepts
::
Value
V
>
#else
template
<
typename
V
>
#endif
using
ch_value_type
=
image_ch_value_t
<
I0
,
V
>
;
/// \}
static_assert
(
std
::
conjunction_v
<
std
::
is_same
<
image_point_t
<
Images
>
,
point_type
>
...
>
,
"The point type of all images to be zipped must be the same."
);
public:
/// Pixel type definitions
/// \{
struct
new_pixel_type
:
Pixel
<
new_pixel_type
>
{
using
reference
=
zip_view
::
reference
;
using
value_type
=
zip_view
::
value_type
;
using
site_type
[[
deprecated
]]
=
zip_view
::
point_type
;
using
point_type
=
zip_view
::
point_type
;
new_pixel_type
(
image_pixel_t
<
Images
>
...
pixels
)
:
m_pixels
{
std
::
move
(
pixels
)...}
{
}
new_pixel_type
(
const
new_pixel_type
&
)
=
default
;
new_pixel_type
(
new_pixel_type
&&
)
=
default
;
new_pixel_type
&
operator
=
(
const
new_pixel_type
&
)
=
delete
;
new_pixel_type
&
operator
=
(
new_pixel_type
&&
)
=
delete
;
point_type
point
()
const
{
return
std
::
get
<
0
>
(
m_pixels
).
point
();
}
reference
val
()
const
{
auto
build_value
=
[](
auto
&&
...
pixels
)
->
reference
{
return
{
pixels
.
val
()...};
};
return
std
::
apply
(
build_value
,
m_pixels
);
}
void
advance
(
point_type
q
)
{
auto
g
=
[
q
](
auto
&&
...
pixels
)
{
(
pixels
.
advance
(
q
),
...);
};
std
::
apply
(
g
,
m_pixels
);
}
private:
std
::
tuple
<
image_pixel_t
<
Images
>
...
>
m_pixels
;
};
/// \}
zip_view
(
Images
...
images
)
:
m_images
{
std
::
move
(
images
)...}
{
}
zip_view
(
const
zip_view
<
Images
...
>&
)
=
default
;
zip_view
(
zip_view
<
Images
...
>&&
)
=
default
;
zip_view
<
Images
...
>&
operator
=
(
const
zip_view
<
Images
...
>&
)
=
delete
;
zip_view
<
Images
...
>&
operator
=
(
zip_view
<
Images
...
>&&
)
=
delete
;
auto
domain
()
const
{
return
std
::
get
<
0
>
(
m_images
).
domain
();
}
decltype
(
auto
)
concretize
()
const
{
return
std
::
get
<
0
>
(
m_images
).
concretize
();
}
#ifdef PYLENE_CONCEPT_TS_ENABLED
template
<
concepts
::
Value
V
>
#else
template
<
typename
V
>
#endif
decltype
(
auto
)
ch_value
()
const
{
return
std
::
get
<
0
>
(
m_images
).
template
ch_value
<
V
>();
}
auto
new_values
()
{
auto
g_new_values
=
[](
auto
&&
...
images
)
{
return
ranges
::
view
::
zip
(
images
.
new_values
()...);
};
return
std
::
apply
(
g_new_values
,
m_images
);
}
auto
new_pixels
()
{
auto
g_new_pixels
=
[](
auto
&&
...
images
)
{
return
ranges
::
view
::
zip_with
([](
auto
&&
...
pixels
)
{
return
new_pixel_type
(
pixels
...);
},
images
.
new_pixels
()...);
};
return
std
::
apply
(
g_new_pixels
,
m_images
);
}
/// Accessible-image related methods
/// \{
template
<
typename
Ret
=
reference
>
std
::
enable_if_t
<
accessible
::
value
,
Ret
>
operator
()(
point_type
p
)
{
mln_precondition
(
all_domain_has
(
p
));
return
this
->
at
(
p
);
}
template
<
typename
Ret
=
reference
>
std
::
enable_if_t
<
accessible
::
value
,
Ret
>
at
(
point_type
p
)
{
auto
g
=
[
p
](
auto
&&
...
images
)
{
return
std
::
forward_as_tuple
(
images
.
at
(
p
)...);
};
return
std
::
apply
(
g
,
m_images
);
}
template
<
typename
Ret
=
new_pixel_type
>
std
::
enable_if_t
<
accessible
::
value
,
Ret
>
new_pixel
(
point_type
p
)
{
mln_precondition
(
all_domain_has
(
p
));
return
this
->
new_pixel_at
(
p
);
}
template
<
typename
Ret
=
new_pixel_type
>
std
::
enable_if_t
<
accessible
::
value
,
Ret
>
new_pixel_at
(
point_type
p
)
{
auto
g
=
[
p
](
auto
&&
...
images
)
{
return
new_pixel_type
(
images
.
new_pixel_at
(
p
)...);
};
return
std
::
apply
(
g
,
m_images
);
}
/// \}
private:
template
<
typename
dummy
=
bool
>
std
::
enable_if_t
<
accessible
::
value
,
dummy
>
all_domain_has
(
point_type
p
)
{
auto
g_has
=
[
p
](
auto
&&
...
images
)
{
return
(
images
.
domain
().
has
(
p
)
&&
...);
};
return
std
::
apply
(
g_has
,
m_images
);
}
};
namespace
view
{
template
<
class
...
Images
>
zip_view
<
Images
...
>
zip
(
Images
...
images
)
{
static_assert
(
std
::
conjunction_v
<
is_a
<
Images
,
experimental
::
Image
>
...
>
,
"All zip arguments must be images."
);
return
zip_view
<
Images
...
>
(
std
::
move
(
images
)...);
}
}
// namespace view
}
// namespace mln
pylene/include/mln/core/rangev3/view/transform.hpp
View file @
ecb47cac
...
...
@@ -33,13 +33,21 @@ namespace mln::ranges
{
private:
// Very bad way to access the private member
auto
fun
()
const
{
return
reinterpret_cast
<
const
detail
::
iter_transform_view_public
<
Rng
,
Fun
>*>
(
this
)
->
fun_
;
}
auto
cfun
()
const
{
return
reinterpret_cast
<
const
detail
::
iter_transform_view_public
<
Rng
,
Fun
>*>
(
this
)
->
fun_
;
}
auto
fun
()
{
return
reinterpret_cast
<
detail
::
iter_transform_view_public
<
Rng
,
Fun
>*>
(
this
)
->
fun_
;
}
public:
using
::
ranges
::
iter_transform_view
<
Rng
,
Fun
>::
iter_transform_view
;
template
<
typename
U
=
void
,
typename
=
std
::
enable_if_t
<
is_segmented_range_v
<
Rng
>,
U
>>
auto
rows
()
const
{
return
::
ranges
::
view
::
transform
(
this
->
base
().
rows
(),
[
fun_
=
cfun
()](
auto
row
)
{
return
::
ranges
::
view
::
iter_transform
(
row
,
fun_
);
});
}
template
<
typename
U
=
void
,
typename
=
std
::
enable_if_t
<
is_segmented_range_v
<
Rng
>,
U
>>
auto
rows
()