Commit 63599df1 authored by Michaël Roynard's avatar Michaël Roynard
Browse files

Migrate equal

parent 8735fca5
......@@ -257,7 +257,7 @@ namespace mln
if (maxv > value_traits<uint16>::max())
std::cerr << "Warning: too many values in the depth (depth image output is wrong)\n";
maxdepth = eval(imcast<uint16>(maxdepth_));
maxdepth = eval(mln::imcast<uint16>(maxdepth_));
}
else
{
......
......@@ -96,7 +96,7 @@ namespace mln
for (unsigned i = 0; i < lambdas.size(); ++i)
{
out[i] = eval(imcast<float>(imtransform(res[i + 1] - res[i], functional::l2norm_t<>())));
out[i] = eval(mln::imcast<float>(imtransform(res[i + 1] - res[i], functional::l2norm_t<>())));
}
return out;
......
......@@ -26,5 +26,5 @@ int main(int argc, char** argv)
resize(out, tree._get_data()->m_pmap);
morpho::reconstruction(tree, dmap, out);
io::imsave(imcast<uint16>(out), argv[2]);
io::imsave(mln::imcast<uint16>(out), argv[2]);
}
......@@ -35,7 +35,7 @@ int main(int argc, char** argv)
{
image2d<uint8> g;
io::imread(argv[i], g);
f = eval(imcast<rgb8>(g));
f = eval(mln::imcast<rgb8>(g));
}
tree = compute_ctos(f);
......
......@@ -35,8 +35,8 @@ int main(int argc, char** argv)
io::imread(argv[1], f);
io::imread(argv[2], g);
auto f_ = imcast<rgb<float>>(f);
auto g_ = imcast<rgb<float>>(g);
auto f_ = mln::imcast<rgb<float>>(f);
auto g_ = mln::imcast<rgb<float>>(g);
auto diff = imtransform(f_ - g_, [](rgb<float> x) -> double { return l2norm_sqr(x); });
auto dims = f.domain().shape();
......
......@@ -257,11 +257,11 @@ bool equal_baseline(const mln::image2d<mln::rgb8>& lhs, const mln::image2d<mln::
}
bool equal(const mln::image2d<mln::uint8>& lhs, const mln::image2d<mln::uint8>& rhs)
{
return mln::experimental::equal(lhs, rhs);
return mln::equal(lhs, rhs);
}
bool equal(const mln::image2d<mln::rgb8>& lhs, const mln::image2d<mln::rgb8>& rhs)
{
return mln::experimental::equal(lhs, rhs);
return mln::equal(lhs, rhs);
}
......
......@@ -12,73 +12,39 @@ namespace mln
/// \brief Compare if two image are equals.
///
/// Two image are said equal if their domains
/// are equals and have the same values.
/// Two image are said equal if they have the same values.
///
/// \param ima1 First image
/// \param ima2 Second image
/// \param lhs First image
/// \param rhs Second image
///
/// \tparam I must model a Readable Forward Image
/// \tparam J must model a Readable Forward Image
/// \tparam LhsImage must model a Readable Forward Image
/// \tparam RhsImage must model a Readable Forward Image
///
/// \return True if image are equals.
///
template <typename I, typename J>
bool equal(const Image<I>& ima1, const Image<J>& ima2);
template <class LhsImage, class RhsImage>
bool equal(LhsImage lhs, RhsImage rhs);
namespace experimental
{
/// \brief Compare if two image are equals.
///
/// Two image are said equal if they have the same values.
///
/// \param lhs First image
/// \param rhs Second image
///
/// \tparam LhsImage must model a Readable Forward Image
/// \tparam RhsImage must model a Readable Forward Image
///
/// \return True if image are equals.
///
template <class LhsImage, class RhsImage>
bool equal(LhsImage lhs, RhsImage rhs);
} // namespace experimental
/******************************************/
/**** Implementation ****/
/******************************************/
template <typename I, typename J>
inline bool equal(const Image<I>& ima1, const Image<J>& ima2)
template <class LhsImage, class RhsImage>
bool equal(LhsImage lhs, RhsImage rhs)
{
mln_pixter(px1, exact(ima1));
mln_pixter(px2, exact(ima2));
static_assert(mln::is_a<LhsImage, experimental::Image>());
static_assert(mln::is_a<RhsImage, experimental::Image>());
auto&& lhs_vals = lhs.new_values();
auto&& rhs_vals = rhs.new_values();
mln_forall (px1, px2)
if (px1->point() != px2->point() or px1->val() != px2->val())
for (auto [lhs_r, rhs_r] : ranges::view::zip(ranges::rows(lhs_vals), ranges::rows(rhs_vals)))
// FIXME: with std::equal you gain performances over ranges::equal here
if (!::ranges::equal(lhs_r, rhs_r))
return false;
return true;
};
namespace experimental
{
template <class LhsImage, class RhsImage>
bool equal(LhsImage lhs, RhsImage rhs)
{
static_assert(mln::is_a<LhsImage, Image>());
static_assert(mln::is_a<RhsImage, Image>());
auto&& lhs_vals = lhs.new_values();
auto&& rhs_vals = rhs.new_values();
for (auto [lhs_r, rhs_r] : ranges::view::zip(ranges::rows(lhs_vals), ranges::rows(rhs_vals)))
// FIXME: with std::equal you gain performances over ranges::equal here
if (!::ranges::equal(lhs_r, rhs_r))
return false;
return true;
}
} // namespace experimental
}
} // namespace mln
......@@ -33,7 +33,7 @@ namespace mln
template <typename I>
struct Image : Object_<I>
{
BOOST_CONCEPT_USAGE(Image) { BOOST_CONCEPT_ASSERT((Image_<I>)); }
// BOOST_CONCEPT_USAGE(Image) { BOOST_CONCEPT_ASSERT((Image_<I>)); }
};
template <typename I>
......
......@@ -19,6 +19,17 @@ namespace mln
template <typename I>
void imsave(const Image<I>& ima, const std::string& path);
namespace experimental
{
template <typename InputImage>
void imsave(InputImage ima, std::ostream& os, FREE_IMAGE_FORMAT fif = FIF_TIFF);
template <typename InputImage>
void imsave(InputImage ima, const std::string& path);
} // namespace experimental
/******************************************/
/**** Implementation ****/
/******************************************/
......@@ -53,5 +64,38 @@ namespace mln
}
}
namespace experimental
{
template <typename InputImage>
void imsave(InputImage ima, std::ostream& os, FREE_IMAGE_FORMAT fif)
{
mln_entering("mln::io::imsave");
freeimage_writer_plugin plugin(os, fif);
Saver2D<std::remove_cv_t<InputImage>> saver;
saver.save(ima, &plugin, false);
mln_exiting();
}
template <typename InputImage>
void imsave(InputImage ima, const std::string& path)
{
if (path == "-")
imsave(ima, std::cout);
else
{
FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(path.c_str());
std::ofstream os(path, std::ios::binary);
if (fif == FIF_UNKNOWN)
imsave(ima, os);
else
imsave(ima, os, fif);
os.close();
}
}
} // namespace experimental
} // namespace io
} // namespace mln
......@@ -22,7 +22,7 @@ namespace mln
template <class I>
class Loader
{
BOOST_CONCEPT_ASSERT((Image<I>));
// BOOST_CONCEPT_ASSERT((Image<I>));
public:
void load(std::istream& s, Image<I>& ima, PluginReader* plugin, bool permissive);
......
......@@ -14,15 +14,18 @@ namespace mln
template <class I>
class Saver
{
BOOST_CONCEPT_ASSERT((Image<I>));
// BOOST_CONCEPT_ASSERT((Image<I>));
public:
virtual ~Saver() = default;
void save(const Image<I>& ima, PluginWriter* plugin, bool permissive);
void save(const Image<I>& ima, PluginWriter* plugin, bool permissive) const;
template <typename = std::enable_if_t<mln::is_a<I, experimental::Image>{}>>
void save(I ima, PluginWriter* plugin, bool permissive) const;
protected:
virtual void m_set_domain(const I& ima, PluginWriter* plugin) = 0;
virtual void m_save(const I& ima, PluginWriter* plugin, bool permissive);
virtual void m_set_domain(const I& ima, PluginWriter* plugin) const = 0;
virtual void m_save(const I& ima, PluginWriter* plugin, bool permissive) const;
};
template <class I, class category = typename image_traits<I>::category>
......@@ -31,7 +34,7 @@ namespace mln
static_assert(std::is_same<typename I::domain_type, box2d>::value, "The domain must be a box2d.");
protected:
virtual void m_set_domain(const I& ima, PluginWriter* plugin);
void m_set_domain(const I& ima, PluginWriter* plugin) const override;
};
template <class I>
......@@ -40,8 +43,8 @@ namespace mln
static_assert(std::is_same<typename I::domain_type, box2d>::value, "The domain must be a box2d.");
protected:
virtual void m_set_domain(const I& ima, PluginWriter* plugin);
virtual void m_save(const I& ima, PluginWriter* plugin, bool permissive);
void m_set_domain(const I& ima, PluginWriter* plugin) const override;
void m_save(const I& ima, PluginWriter* plugin, bool permissive) const override;
};
/******************************************/
......@@ -49,7 +52,7 @@ namespace mln
/******************************************/
template <class I>
void Saver<I>::save(const Image<I>& ima_, PluginWriter* plugin, bool permissive)
void Saver<I>::save(const Image<I>& ima_, PluginWriter* plugin, bool permissive) const
{
const I& ima = exact(ima_);
......@@ -65,33 +68,58 @@ namespace mln
}
template <class I>
void Saver<I>::m_save(const I& ima, PluginWriter* plugin, bool permissive)
template <typename>
void Saver<I>::save(I ima, PluginWriter* plugin, bool permissive) const
{
if (not plugin->can_write(typeid(mln_value(I))))
{
std::string msg = "The plugin does not support writing " + internal::demangle(typeid(mln_value(I)).name());
throw MLNIOException(msg);
}
plugin->set_value_type(typeid(mln_value(I)));
this->m_set_domain(ima, plugin);
this->m_save(ima, plugin, permissive);
}
template <class I>
void Saver<I>::m_save(const I& ima, PluginWriter* plugin, bool permissive) const
{
(void)permissive;
std::function<void(void*)> write_next_pixel = plugin->get_write_next_pixel_method();
mln_foreach (mln_value(I) v, ima.values())
if constexpr (is_a<I, experimental::Image>{})
{
for (auto v : const_cast<I*>(&ima)->new_values())
{
write_next_pixel((void*)&v);
}
}
else
{
write_next_pixel((void*)&v);
mln_foreach (mln_value(I) v, ima.values())
{
write_next_pixel((void*)&v);
}
}
}
template <class I, class category>
void Saver2D<I, category>::m_set_domain(const I& ima, PluginWriter* plugin)
void Saver2D<I, category>::m_set_domain(const I& ima, PluginWriter* plugin) const
{
PluginWriter2D* plug = static_cast<PluginWriter2D*>(plugin);
plug->set_domain(ima.domain());
}
template <class I>
void Saver2D<I, raw_image_tag>::m_set_domain(const I& ima, PluginWriter* plugin)
void Saver2D<I, raw_image_tag>::m_set_domain(const I& ima, PluginWriter* plugin) const
{
PluginWriter2D* plug = static_cast<PluginWriter2D*>(plugin);
plug->set_domain(ima.domain());
}
template <class I>
void Saver2D<I, raw_image_tag>::m_save(const I& ima, PluginWriter* plugin, bool permissive)
void Saver2D<I, raw_image_tag>::m_save(const I& ima, PluginWriter* plugin, bool permissive) const
{
(void)permissive;
......
......@@ -114,7 +114,7 @@ namespace mln
{
if (max_depth < value_traits<uint16>::max())
{
tree = morpho::maxtree_indexes(imcast<uint16>(ord), nbh_t());
tree = morpho::maxtree_indexes(mln::imcast<uint16>(ord), nbh_t());
}
else
{
......
......@@ -8,34 +8,30 @@
TEST(Core, Algorithm_Equal)
{
using namespace mln;
image2d<uint8> ima(10, 10);
image2d<uint8> out(10, 10);
mln::image2d<mln::uint8> ima(10, 10);
mln::image2d<mln::uint8> out(10, 10);
mln::iota(ima, 0);
mln::iota(out, 0);
ASSERT_TRUE(equal(ima, out));
ASSERT_TRUE(mln::equal(ima, out));
point2d p = {2, 3};
out(p) = 12;
ASSERT_TRUE(not equal(ima, out));
mln::point2d p = {2, 3};
out(p) = 12;
ASSERT_TRUE(not mln::equal(ima, out));
}
TEST(Core, Algorithm_ExperimentalEqual)
{
using namespace mln;
image2d<uint8> ima(10, 10);
image2d<uint8> out(10, 10);
mln::image2d<mln::uint8> ima(10, 10);
mln::image2d<mln::uint8> out(10, 10);
mln::iota(ima, 0);
mln::iota(out, 0);
ASSERT_TRUE(experimental::equal(ima, out));
ASSERT_TRUE(mln::equal(ima, out));
point2d p = {2, 3};
out(p) = 12;
ASSERT_TRUE(not experimental::equal(ima, out));
mln::point2d p = {2, 3};
out(p) = 12;
ASSERT_TRUE(not mln::equal(ima, out));
}
......@@ -3,6 +3,7 @@
#include <mln/core/grays.hpp>
#include <mln/core/image/image2d.hpp>
#include <mln/core/image/morphers/casted_image.hpp>
#include <mln/core/image/private/image_operators.hpp>
#include <mln/io/imprint.hpp>
#include <mln/io/imread.hpp>
#include <mln/io/imsave.hpp>
......@@ -64,6 +65,7 @@ TEST(IO, FreeImage_pbm)
TEST(IO, FreeImage_slow_pgm)
{
using namespace mln;
using namespace mln::experimental::ops;
image2d<uint8> ima;
image2d<uint8> ref(5, 5);
......@@ -72,16 +74,18 @@ TEST(IO, FreeImage_slow_pgm)
io::imread(fixtures::ImagePath::concat_with_filename("iota2d.pgm"), ima);
ASSERT_TRUE(equal(ima, ref));
auto tmp = 2u * ref;
io::imsave(imcast<uint32>(tmp), "test.tiff");
auto imax2 = 2u * ref;
io::experimental::imsave(experimental::imcast<uint32>(imax2), "test.tiff");
image2d<unsigned> ima2;
io::imread("test.tiff", ima2);
ASSERT_TRUE(mln::equal(ima2, tmp));
ASSERT_TRUE(mln::equal(ima2, imax2));
}
TEST(IO, FreeImage_slow_ppm)
{
using namespace mln;
using namespace mln::experimental::ops;
image2d<rgb8> ima;
image2d<rgb8> ref(5, 5);
......@@ -96,7 +100,7 @@ TEST(IO, FreeImage_slow_ppm)
ASSERT_TRUE(equal(ima, ref));
auto tmp = 2u * ref;
io::imsave(imcast<rgb8>(tmp), "test.tiff");
io::experimental::imsave(experimental::imcast<rgb8>(tmp), "test.tiff");
io::imread("test.tiff", ima);
ASSERT_TRUE(mln::equal(ima, 2 * ref));
}
......@@ -104,6 +108,7 @@ TEST(IO, FreeImage_slow_ppm)
TEST(IO, FreeImage_slow_pbm)
{
using namespace mln;
using namespace mln::experimental::ops;
image2d<bool> ima;
image2d<bool> ref(5, 5);
......@@ -111,7 +116,7 @@ TEST(IO, FreeImage_slow_pbm)
mln_foreach (point2d p, ref.domain())
ref(p) = ((p[0] % 2) == (p[1] % 2));
io::imsave(lnot(ref), "test.tiff");
io::experimental::imsave(not ref, "test.tiff");
io::imread("test.tiff", ima);
ASSERT_TRUE(mln::equal(ima, lnot(ref)));
ASSERT_TRUE(mln::equal(ima, not ref));
}
......@@ -30,6 +30,6 @@ TEST(Morpho, hit_or_miss)
ASSERT_TRUE(all(out == out2));
auto out3 = morpho::hit_or_miss(imcast<uint8>(ima), win1, win2);
ASSERT_TRUE(all(imcast<uint8>(out) == out3));
auto out3 = morpho::hit_or_miss(mln::imcast<uint8>(ima), win1, win2);
ASSERT_TRUE(all(mln::imcast<uint8>(out) == out3));
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment