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
f329e4b1
Commit
f329e4b1
authored
Dec 18, 2018
by
Michaël Roynard
Browse files
Fix adaptor/transform
parent
9c2000d3
Pipeline
#12648
failed with stages
in 7 minutes and 42 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
doc/source/labeling/local_extrema.rst
View file @
f329e4b1
...
...
@@ -7,15 +7,15 @@ Include :file:`<mln/labeling/local_extrema.hpp>`
#. .. cpp:function:: \
template <class Label_t, class I, class N> \
ch_value_t<I, Label_t> local_minima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel)
image_
ch_value_t<I, Label_t> local_minima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel)
#. .. cpp:function:: \
template <class Label_t, class I, class N> \
ch_value_t<I, Label_t> local_maxima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel)
image_
ch_value_t<I, Label_t> local_maxima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel)
#. .. cpp:function:: \
template <class Label_t, class I, class N, class Compare> \
ch_value_t<I, Label_t> local_minima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel, Compare cmp)
image_
ch_value_t<I, Label_t> local_minima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel, Compare cmp)
Labelize the local minima (1) or maxima (2) of an image with an optional
comparaison function ``cmp`` (3).
...
...
doc/source/morpho/watershed.rst
View file @
f329e4b1
...
...
@@ -7,7 +7,7 @@ Include :file:`<mln/morpho/watershed.hpp>`
.. cpp:function:: template <class Label_t, class I, class N> \
ch_value_t<I, Label_t> watershed(const Image<I>& ima, const Neighborhood<N>& nbh, int& nlabel)
image_
ch_value_t<I, Label_t> watershed(const Image<I>& ima, const Neighborhood<N>& nbh, int& nlabel)
Watershed by immersion as defined in [BM92]_. The catchment basins are
labeled from 1 to n, and the special label 0 is used for watershed lines.
...
...
pylene/include/mln/core/image/internal/initializer.hpp
View file @
f329e4b1
...
...
@@ -23,18 +23,27 @@ namespace mln
{
typedef
I
type
;
};
}
}
// namespace internal
struct
init
{
};
template
<
typename
I
>
struct
New_Image
;
template
<
typename
V
,
class
I
>
internal
::
initializer
<
mln_ch_value
(
I
,
V
),
I
>
imchvalue
(
const
Image
<
I
>&
ref
);
template
<
typename
V
,
class
I
>
internal
::
initializer
<
mln_ch_value
(
I
,
V
),
I
>
imchvalue_new
(
const
New_Image
<
I
>&
ref
);
template
<
class
I
>
internal
::
initializer
<
mln_concrete
(
I
),
I
>
imconcretize
(
const
Image
<
I
>&
ref
);
template
<
class
I
>
internal
::
initializer
<
mln_concrete
(
I
),
I
>
imconcretize_new
(
const
New_Image
<
I
>&
ref
);
/******************************************/
/**** Implementation ****/
/******************************************/
...
...
@@ -216,7 +225,7 @@ namespace mln
int
m_border
;
};
}
//
end of
namespace
mln::
internal
}
// namespace internal
template
<
typename
V
,
class
I
>
internal
::
initializer
<
mln_ch_value
(
I
,
V
),
I
>
imchvalue
(
const
Image
<
I
>&
_ref
)
...
...
@@ -225,6 +234,13 @@ namespace mln
return
internal
::
initializer
<
mln_ch_value
(
I
,
V
),
I
>
(
ref
);
}
template
<
typename
V
,
class
I
>
internal
::
initializer
<
mln_ch_value
(
I
,
V
),
I
>
imchvalue_new
(
const
New_Image
<
I
>&
_ref
)
{
const
I
&
ref
=
*
static_cast
<
const
I
*>
(
&
_ref
);
return
internal
::
initializer
<
mln_ch_value
(
I
,
V
),
I
>
(
ref
);
}
template
<
class
I
>
internal
::
initializer
<
mln_concrete
(
I
),
I
>
imconcretize
(
const
Image
<
I
>&
_ref
)
{
...
...
@@ -232,6 +248,13 @@ namespace mln
return
internal
::
initializer
<
mln_concrete
(
I
),
I
>
(
ref
);
}
template
<
class
I
>
internal
::
initializer
<
mln_concrete
(
I
),
I
>
imconcretize_new
(
const
New_Image
<
I
>&
_ref
)
{
const
I
&
ref
=
*
static_cast
<
const
I
*>
(
&
_ref
);
return
internal
::
initializer
<
mln_concrete
(
I
),
I
>
(
ref
);
}
}
// end of namespace mln
#endif //! MLN_CORE_IMAGE_INTERNAL_INITIALIZER_HPP
pylene/include/mln/core/image/private/image_traits.hpp
View file @
f329e4b1
#pragma once
// FIXME: backward compatibility
#include <mln/core/image_traits.hpp> // image_ch_value_t
namespace
mln
{
...
...
@@ -47,8 +50,9 @@ namespace mln
// Change value type trait
template
<
class
I
,
class
V
>
using
image_ch_value_t
=
typename
I
::
template
ch_value_type
<
V
>;
// FIXME: defined in mln/core/image_traits
// template <class I, class V>
// using image_ch_value_t = typename I::template ch_value_type<V>;
// Category trait
template
<
class
I
>
...
...
pylene/include/mln/core/image/view/adaptor.hpp
View file @
f329e4b1
...
...
@@ -101,7 +101,9 @@ namespace mln
template
<
class
I
>
struct
image_adaptor
:
detail
::
image_adaptor_base_indexable
<
I
>
,
detail
::
image_adaptor_base_with_extension
<
I
>
struct
image_adaptor
:
detail
::
image_adaptor_base_indexable
<
I
>
,
detail
::
image_adaptor_base_with_extension
<
I
>
,
New_Image
<
I
>
{
public:
/// Type definitions
...
...
pylene/include/mln/core/image/view/transform.hpp
View file @
f329e4b1
...
...
@@ -3,6 +3,7 @@
#include <mln/core/image/image.hpp>
#include <mln/core/image/view/adaptor.hpp>
#include <mln/core/rangev3/view/transform.hpp>
#include <type_traits>
namespace
mln
...
...
@@ -10,7 +11,7 @@ namespace mln
template
<
class
I
,
class
F
>
class
transform_view
:
public
image_adaptor
<
I
>
,
public
New_Image
<
transform_view
<
I
,
F
>>
class
transform_view
:
public
image_adaptor
<
I
>
{
using
fun_t
=
F
;
fun_t
fun_
;
...
...
@@ -18,27 +19,32 @@ namespace mln
public:
/// Type definitions
/// \{
using
reference
=
std
::
invoke_result_t
<
F
&
,
typename
I
::
reference
>
;
using
value_type
=
std
::
decay_t
<
reference
>
;
using
point_type
=
typename
I
::
point_type
;
using
reference
=
std
::
invoke_result_t
<
F
&
,
image_reference_t
<
I
>>
;
using
value_type
=
std
::
remove_cv_t
<
std
::
remove_reference_t
<
reference
>>
;
using
point_type
=
image_point_t
<
I
>
;
using
domain_type
=
image_domain_t
<
I
>
;
static_assert
(
!
(
std
::
is_rvalue_reference_v
<
reference
>
&&
!
std
::
is_reference_v
<
typename
I
::
reference
>
),
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
=
ch_value_t
<
I
,
value_type
>
;
using
concrete_type
=
image_
ch_value_t
<
I
,
value_type
>
;
template
<
class
V
>
using
ch_value_type
=
ch_value_t
<
I
,
V
>
;
template
<
typename
V
>
using
ch_value_type
=
image_
ch_value_t
<
I
,
V
>
;
/// \}
/// Traits & Image Properties
/// \{
using
accessible
=
typename
I
::
accessible
;
using
indexable
=
typename
I
::
indexable
;
using
extension_category
=
mln
::
extension
::
none_extension_tag
;
// FIXME: should be improved
using
accessible
=
image_accessible_t
<
I
>
;
using
indexable
=
image_indexable_t
<
I
>
;
using
view
=
std
::
true_type
;
using
extension_category
=
image_extension_category_t
<
I
>
;
// 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
>>
;
/// \}
private:
...
...
@@ -82,6 +88,10 @@ namespace mln
/// \}
/////////////////
// Image proxy //
/////////////////
transform_view
(
I
ima
,
F
fun
)
:
transform_view
::
image_adaptor
{
std
::
move
(
ima
)}
,
fun_
{
std
::
move
(
fun
)}
...
...
@@ -99,61 +109,80 @@ namespace mln
{
}
auto
new_values
()
{
return
mln
::
ranges
::
view
::
transform
(
this
->
base
().
new_values
(),
fun_
);
}
decltype
(
auto
)
concretize
()
const
{
return
imchvalue
<
value_type
>
(
this
->
base
());
}
auto
new_pixels
()
{
using
R
=
decltype
(
this
->
base
().
new_pixels
());
auto
pxwrapper
=
[
fun
=
this
->
fun_
](
::
ranges
::
range_value_t
<
R
>
px
)
{
return
new_pixel_type
{
fun
,
std
::
move
(
px
)};
};
return
mln
::
ranges
::
view
::
transform
(
this
->
base
().
new_pixels
(),
pxwrapper
);
}
template
<
class
U
>
decltype
(
auto
)
concretize
()
const
{
return
imchvalue_new
<
value_type
>
(
this
->
base
());
}
#ifdef PYLENE_CONCEPT_TS_ENABLED
template
<
concepts
::
Value
Val
>
#else
template
<
typename
Val
>
#endif
decltype
(
auto
)
ch_value
()
const
{
return
imchvalue
<
U
>
(
this
->
base
());
return
imchvalue
_new
<
Val
>
(
this
->
base
());
}
auto
new_values
()
{
return
mln
::
ranges
::
view
::
transform
(
this
->
base
().
new_values
(),
fun_
);
}
auto
new_pixels
()
/// Indexable-image related methods
/// \{
template
<
typename
dummy
=
I
>
reference
operator
[](
image_index_t
<
dummy
>
i
)
{
using
R
=
decltype
(
this
->
base
().
new_pixels
());
auto
pxwrapper
=
[
fun
=
this
->
fun_
](
::
ranges
::
range_value_t
<
R
>
px
)
{
return
new_pixel_type
{
fun
,
std
::
move
(
px
)};
};
return
mln
::
ranges
::
view
::
transform
(
this
->
base
().
new_pixels
(),
pxwrapper
);
return
std
::
invoke
(
fun_
,
this
->
base
()[
i
]);
}
/// \}
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
(
this
->
base
().
domain
().
has
(
p
));
mln_precondition
(
this
->
domain
().
has
(
p
));
return
std
::
invoke
(
fun_
,
this
->
base
()(
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_
,
this
->
base
().
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
(
this
->
base
().
domain
().
has
(
p
));
mln_precondition
(
this
->
domain
().
has
(
p
));
return
{
fun_
,
this
->
base
().
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_
,
this
->
base
().
new_pixel_at
(
p
)};
}
/// \}
template
<
typename
dummy
=
I
>
reference
operator
[](
typename
dummy
::
size_type
i
)
{
return
std
::
invoke
(
fun_
,
this
->
base
()[
i
]);
}
/// Raw-image related methods
/// \{
auto
data
()
const
=
delete
;
auto
data
()
=
delete
;
auto
strides
(
int
)
const
=
delete
;
/// \}
};
template
<
class
I1
,
class
I2
,
class
F
>
class
transform2_view
:
public
New_Image
<
transform2_view
<
I1
,
I2
,
F
>>
{
using
fun_t
=
F
;
// FIXME something with semiregular_t<F> ?
using
fun_t
=
F
;
I1
m_ima1
;
I2
m_ima2
;
fun_t
fun_
;
...
...
@@ -174,10 +203,10 @@ namespace mln
using
indexable
=
std
::
false_type
;
// Preservative behavior
using
extension_category
=
mln
::
extension
::
none_extension_tag
;
// Preservative behavior (may be too preservative)
using
concrete_type
=
ch_value_t
<
I1
,
value_type
>
;
using
concrete_type
=
image_
ch_value_t
<
I1
,
value_type
>
;
template
<
class
V
>
using
ch_value_type
=
ch_value_t
<
I1
,
V
>
;
using
ch_value_type
=
image_
ch_value_t
<
I1
,
V
>
;
/// \}
public:
...
...
pylene/include/mln/core/image_traits.hpp
View file @
f329e4b1
...
...
@@ -23,7 +23,7 @@
namespace
mln
{
template
<
class
I
,
class
V
>
using
ch_value_t
=
typename
I
::
template
ch_value_type
<
V
>;
using
image_
ch_value_t
=
typename
I
::
template
ch_value_type
<
V
>;
struct
[[
deprecated
]]
image_dynamic_tag
{
...
...
@@ -37,7 +37,7 @@ namespace mln
struct
Image
;
template
<
typename
I
>
struct
image_traits
:
image_traits
<
typename
std
::
decay
<
I
>::
type
>
struct
image_traits
:
image_traits
<
typename
std
::
decay
<
I
>::
type
>
{
};
...
...
@@ -217,7 +217,7 @@ namespace mln
};
#define MLN_GENERATE_META_IMAGE_OPERATORS(meta_op, op) \
struct meta_op \
struct meta_op
\
{ \
template <typename Image> \
struct apply \
...
...
@@ -244,6 +244,6 @@ namespace mln
MLN_GENERATE_META_IMAGE_OPERATORS
(
image_meta_const_value_iterator
,
image_const_value_iterator
)
MLN_GENERATE_META_IMAGE_OPERATORS
(
image_meta_pixel_iterator
,
image_pixel_iterator
)
MLN_GENERATE_META_IMAGE_OPERATORS
(
image_meta_const_pixel_iterator
,
image_const_pixel_iterator
)
}
}
// namespace mln
#endif
/* !MLN_CORE_IMAGE_TRAITS_HPP */
tests/core/image/view/transform.cpp
View file @
f329e4b1
...
...
@@ -10,6 +10,8 @@
#include <mln/core/rangev3/foreach.hpp>
#include <mln/core/rangev3/view/zip.hpp>
#include <helpers.hpp>
#include <gtest/gtest.h>
...
...
@@ -18,14 +20,10 @@ namespace archetypes = mln::archetypes;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template
<
concepts
::
Image
Ima
>
template
<
concepts
::
View
Image
Ima
>
void
foo
(
Ima
)
{
}
template
<
concepts
::
Pixel
Pix
>
void
bar
(
Pix
)
{
}
#endif // PYLENE_CONCEPT_TS_ENABLED
TEST
(
Core
,
TransformedImage_transform_byval_rvalue
)
...
...
@@ -38,30 +36,39 @@ TEST(Core, TransformedImage_transform_byval_rvalue)
iota
(
ima
,
0
);
{
auto
out
=
view
::
transform
(
ima
,
[](
int
x
)
{
return
x
*
2
;
});
#ifdef PYLENE_CONCEPT_TS_ENABLED
// bar(std::decay_t<decltype(out)>::new_pixel_type{});
foo
(
out
);
#endif // PYLENE_CONCEPT_TS_ENABLED
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert
(
concepts
::
ConcreteImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
OutputImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
ViewImage
<
decltype
(
out
)
>
);
static_assert
(
concepts
::
IndexableAndAccessibleImage
<
decltype
(
out
)
>
);
static_assert
(
concepts
::
BidirectionalImage
<
decltype
(
out
)
>
);
static_assert
(
not
concepts
::
RawImage
<
decltype
(
out
)
>
);
static_assert
(
not
concepts
::
OutputImage
<
decltype
(
out
)
>
);
#endif // PYLENE_CONCEPT_TS_ENABLED
// Test pixel iteration
// check that properties of pixels are preserved (point + index)
{
mln_foreach_new
((
auto
[
px1
,
px2
]),
mln
::
ranges
::
view
::
zip
(
ima
.
new_pixels
(),
out
.
new_pixels
())){
ASSERT_EQ
(
px1
.
point
(),
px2
.
point
());
// ASSERT_EQ(px1.index(), px2.index());
ASSERT_EQ
(
2
*
px1
.
val
(),
px2
.
val
());
// ASSERT_EQ(&px2->image(), &out);
{
auto
rng
=
mln
::
ranges
::
view
::
zip
(
ima
.
new_pixels
(),
out
.
new_pixels
());
mln_foreach_new
((
auto
[
px1
,
px2
]),
rng
)
{
ASSERT_EQ
(
px1
.
point
(),
px2
.
point
());
// ASSERT_EQ(px1.index(), px2.index());
ASSERT_EQ
(
2
*
px1
.
val
(),
px2
.
val
());
// ASSERT_EQ(&px2->image(), &out);
}
}
// Test value iteration
{
auto
rng
=
mln
::
ranges
::
view
::
zip
(
ima
.
new_values
(),
out
.
new_values
());
mln_foreach_new
((
auto
[
v1
,
v2
]),
rng
)
ASSERT_EQ
(
2
*
v1
,
v2
);
}
}
}
// Test value iteration
{
mln_foreach_new
((
auto
[
v1
,
v2
]),
mln
::
ranges
::
view
::
zip
(
ima
.
new_values
(),
out
.
new_values
()))
ASSERT_EQ
(
2
*
v1
,
v2
);
}
}
}
TEST
(
Core
,
TransformedImage_transform_byval_chain
)
{
using
namespace
mln
;
...
...
@@ -73,24 +80,36 @@ TEST(Core, TransformedImage_transform_byval_chain)
{
auto
out
=
view
::
transform
(
view
::
transform
(
ima
,
[](
int
x
)
{
return
x
*
2
;
}),
[](
int
x
)
{
return
x
*
2
;
});
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert
(
concepts
::
ConcreteImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
OutputImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
ViewImage
<
decltype
(
out
)
>
);
static_assert
(
concepts
::
IndexableAndAccessibleImage
<
decltype
(
out
)
>
);
static_assert
(
concepts
::
BidirectionalImage
<
decltype
(
out
)
>
);
static_assert
(
not
concepts
::
RawImage
<
decltype
(
out
)
>
);
static_assert
(
not
concepts
::
OutputImage
<
decltype
(
out
)
>
);
#endif // PYLENE_CONCEPT_TS_ENABLED
// Test pixel iteration
// check that properties of pixels are preserved (point + index)
{
mln_foreach_new
((
auto
[
px1
,
px2
]),
mln
::
ranges
::
view
::
zip
(
ima
.
new_pixels
(),
out
.
new_pixels
())){
ASSERT_EQ
(
px1
.
point
(),
px2
.
point
());
// ASSERT_EQ(px1.index(), px2.index());
ASSERT_EQ
(
4
*
px1
.
val
(),
px2
.
val
());
// ASSERT_EQ(&px2->image(), &out);
{
auto
rng
=
mln
::
ranges
::
view
::
zip
(
ima
.
new_pixels
(),
out
.
new_pixels
());
mln_foreach_new
((
auto
[
px1
,
px2
]),
rng
)
{
ASSERT_EQ
(
px1
.
point
(),
px2
.
point
());
// ASSERT_EQ(px1.index(), px2.index());
ASSERT_EQ
(
4
*
px1
.
val
(),
px2
.
val
());
// ASSERT_EQ(&px2->image(), &out);
}
}
// Test value iteration
{
mln_foreach_new
((
auto
[
v1
,
v2
]),
mln
::
ranges
::
view
::
zip
(
ima
.
new_values
(),
out
.
new_values
()))
ASSERT_EQ
(
4
*
v1
,
v2
);
}
}
}
// Test value iteration
{
mln_foreach_new
((
auto
[
v1
,
v2
]),
mln
::
ranges
::
view
::
zip
(
ima
.
new_values
(),
out
.
new_values
()))
ASSERT_EQ
(
4
*
v1
,
v2
);
}
}
}
TEST
(
Core
,
Transform_Support_Writable
)
{
using
namespace
mln
;
...
...
@@ -104,6 +123,23 @@ TEST(Core, Transform_Support_Writable)
auto
c2
=
view
::
transform
(
ima
,
[](
const
std
::
pair
<
int
,
int
>&
x
)
{
return
x
.
second
;
});
fill
(
ima
,
std
::
make_pair
(
12
,
12
));
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert
(
concepts
::
ConcreteImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
OutputImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
ViewImage
<
decltype
(
c1
)
>
);
static_assert
(
concepts
::
IndexableAndAccessibleImage
<
decltype
(
c1
)
>
);
static_assert
(
concepts
::
BidirectionalImage
<
decltype
(
c1
)
>
);
static_assert
(
not
concepts
::
RawImage
<
decltype
(
c1
)
>
);
static_assert
(
concepts
::
OutputImage
<
decltype
(
c1
)
>
);
static_assert
(
concepts
::
ViewImage
<
decltype
(
c2
)
>
);
static_assert
(
concepts
::
IndexableAndAccessibleImage
<
decltype
(
c2
)
>
);
static_assert
(
concepts
::
BidirectionalImage
<
decltype
(
c2
)
>
);
static_assert
(
not
concepts
::
RawImage
<
decltype
(
c2
)
>
);
static_assert
(
not
concepts
::
OutputImage
<
decltype
(
c2
)
>
);
#endif // PYLENE_CONCEPT_TS_ENABLED
// FIXME: use fill once adapted
mln_foreach_new
(
auto
&&
val
,
c1
.
new_values
())
val
=
69
;
...
...
@@ -113,29 +149,32 @@ TEST(Core, Transform_Support_Writable)
// Test pixel iteration
// check that properties of pixels are preserved (point + index)
{
mln_foreach_new
((
auto
[
px1
,
px2
,
px3
]),
mln
::
ranges
::
view
::
zip
(
ima
.
new_pixels
(),
c1
.
new_pixels
(),
c2
.
new_pixels
())){
{
auto
rng
=
mln
::
ranges
::
view
::
zip
(
ima
.
new_pixels
(),
c1
.
new_pixels
(),
c2
.
new_pixels
());
mln_foreach_new
((
auto
[
px1
,
px2
,
px3
]),
rng
)
{
ASSERT_EQ
(
px1
.
point
(),
px2
.
point
());
ASSERT_EQ
(
px1
.
point
(),
px3
.
point
());
// ASSERT_EQ(px1.index(), px2.index());
ASSERT_EQ
(
std
::
make_pair
(
69
,
12
),
px1
.
val
());
ASSERT_EQ
(
69
,
px2
.
val
());
ASSERT_EQ
(
12
,
px3
.
val
());
// ASSERT_EQ(&px2->image(), &out);
}
}
// Test value iteration
{
mln_foreach_new
((
auto
[
v1
,
v2
,
v3
]),
mln
::
ranges
::
view
::
zip
(
ima
.
new_values
(),
c1
.
new_values
(),
c2
.
new_values
()))
{
ASSERT_EQ
(
std
::
make_pair
(
69
,
12
),
v1
);
ASSERT_EQ
(
69
,
v2
);
ASSERT_EQ
(
12
,
v3
);
ASSERT_EQ
(
px1
.
point
(),
px3
.
point
());
// ASSERT_EQ(px1.index(), px2.index());
ASSERT_EQ
(
std
::
make_pair
(
69
,
12
),
px1
.
val
());
ASSERT_EQ
(
69
,
px2
.
val
());
ASSERT_EQ
(
12
,
px3
.
val
());
// ASSERT_EQ(&px2->image(), &out);
}
}
// Test value iteration
{
auto
rng
=
mln
::
ranges
::
view
::
zip
(
ima
.
new_values
(),
c1
.
new_values
(),
c2
.
new_values
());
mln_foreach_new
((
auto
[
v1
,
v2
,
v3
]),
rng
)
{
ASSERT_EQ
(
std
::
make_pair
(
69
,
12
),
v1
);
ASSERT_EQ
(
69
,
v2
);
ASSERT_EQ
(
12
,
v3
);
}
}
}
}
}
}
int
times_two
(
int
x
)
{
...
...
@@ -151,6 +190,16 @@ TEST(Core, Transform_Supports_Function)
auto
c
=
mln
::
view
::
transform
(
ima
,
times_two
);
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert
(
concepts
::
ConcreteImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
OutputImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
ViewImage
<
decltype
(
c
)
>
);
static_assert
(
concepts
::
IndexableAndAccessibleImage
<
decltype
(
c
)
>
);
static_assert
(
concepts
::
BidirectionalImage
<
decltype
(
c
)
>
);
static_assert
(
not
concepts
::
RawImage
<
decltype
(
c
)
>
);
static_assert
(
not
concepts
::
OutputImage
<
decltype
(
c
)
>
);
#endif // PYLENE_CONCEPT_TS_ENABLED
// FIXME: ASSERT_IMAGES_EQ(ref, c);
}
...
...
@@ -164,11 +213,19 @@ TEST(Core, Transform_Supports_PointerToMemberFunction)
auto
c
=
mln
::
view
::
transform
(
ima
,
&
std
::
pair
<
int
,
int
>::
first
);
// FIXME: mln::fill(c, 69);
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert
(
concepts
::
ConcreteImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
OutputImage
<
decltype
(
ima
)
>
);
static_assert
(
concepts
::
ViewImage
<
decltype
(
c
)
>
);
static_assert
(
concepts
::
IndexableAndAccessibleImage
<
decltype
(
c
)
>
);
static_assert
(
concepts
::
BidirectionalImage
<
decltype
(
c
)
>
);
static_assert
(
not
concepts
::
RawImage
<
decltype
(
c
)
>
);
static_assert
(
concepts
::
OutputImage
<
decltype
(
c
)
>
);
#endif // PYLENE_CONCEPT_TS_ENABLED
// FIXME: mln::fill(c, 69);
mln_foreach_new
(
auto
&
val
,
c
.
new_values
())
val
=
69
;
// FIXME: ASSERT_IMAGES_EQ(ref, c);
}
Write
Preview