Skip to content

Commit

Permalink
initial add of basic image loader - #15
Browse files Browse the repository at this point in the history
  • Loading branch information
timdewhirst committed Feb 7, 2023
1 parent 3d52723 commit 88d4c56
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 25 deletions.
1 change: 1 addition & 0 deletions pybind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ if (BUILD_PYBIND)
core/vector.cpp
core/pixel_types.cpp
core/image.cpp
core/loader.cpp
)

find_package(fmt CONFIG REQUIRED)
Expand Down
41 changes: 17 additions & 24 deletions pybind/core/image.cpp
Original file line number Diff line number Diff line change
@@ -1,44 +1,26 @@

// openpiv
#include "core/image.h"
#include "core/util.h"

using namespace openpiv;
using namespace openpiv::core;

// local
#include "pyutils.h"

// std
#include <sstream>
#include <vector>

// pybind
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/operators.h>

// std
#include <sstream>


namespace py = pybind11;


template <template <typename> class I,
template <typename> class P,
typename U>
struct image_type_trait
{
template <size_t N=64>
static constexpr char_array<N> name()
{
return cat<N>(to_array<8>("image"), pixel_type_trait<P, U>::name());
}
};

// test
static_assert(image_type_trait<image, g, uint8_t>::name() == "image_g_u8");
static_assert(image_type_trait<image, rgba, uint16_t>::name() == "image_rgba_u16");
static_assert(image_type_trait<image, yuva, uint32_t>::name() == "image_yuva_u32");
static_assert(image_type_trait<image, complex, double>::name() == "image_c_f");


template <template <typename> class I,
template <typename> class P,
typename U>
Expand All @@ -53,7 +35,18 @@ bool add_image_(py::module& m)
return ss.str();
};

py::class_<image_t>(m, &image_type_trait<I, P, U>::name()[0])
py::class_<image_t>(m, &image_type_trait<I, P, U>::name()[0], py::buffer_protocol())
.def_buffer([](image_t& image) -> py::buffer_info {
const auto dimensions = image_type_trait<I, P, U>::dimensions(image);
const auto strides = image_type_trait<I, P, U>::strides(image);
return py::buffer_info(
image.data(), // pointer to raw data
sizeof( U ), // size of a single underlying data element
py::format_descriptor<U>::format(), // mapping to python char code for underlying
dimensions.size(), // number of dimensions
dimensions, // dimensions in matrix convention
strides); // strides in matrix convention
})
.def(py::init())
.def(py::init<image_t>())
.def(py::init<uint32_t, uint32_t>())
Expand Down
55 changes: 55 additions & 0 deletions pybind/core/loader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

// openpiv
#include "core/exception_builder.h"
#include "core/image.h"
#include "core/util.h"
#include "loaders/image_loader.h"

using namespace openpiv;
using namespace openpiv::core;

// local
#include "pyutils.h"

// std
#include <fstream>
#include <vector>

// pybind
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;


void add_loader(py::module& m)
{
m.def( "load_g_u16",
[](const std::string& filename) -> std::vector<image_g_16>
{
// open file
std::ifstream is(filename, std::ios::binary);
if ( !is.is_open() )
core::exception_builder<std::runtime_error>() << "failed to open " << filename;

// find loader
auto loader{ core::image_loader_registry::find(is) };
if ( !loader )
core::exception_builder<std::runtime_error>() << "failed to find loader for " << filename;

// open image file
if ( !loader->open(is) )
core::exception_builder<std::runtime_error>() << "failed to open with loader " << filename;

// load all images
std::vector<image_g_16> images;
for ( size_t index = 0; index < loader->num_images(); ++index )
{
image_g_16 im;
loader->extract( index, im );
images.push_back( std::move( im ) );
}
return images;
});
}

2 changes: 2 additions & 0 deletions pybind/core/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ void add_size(py::module &);
void add_vector(py::module &);
void add_pixel_types(py::module &);
void add_image(py::module &);
void add_loader(py::module &);

PYBIND11_MODULE(pyopenpivcore, m) {
m.doc() = R"pbdoc(
Expand All @@ -35,6 +36,7 @@ PYBIND11_MODULE(pyopenpivcore, m) {
add_vector(m);
add_pixel_types(m);
add_image(m);
add_loader(m);

#ifdef VERSION_INFO
m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO);
Expand Down
49 changes: 48 additions & 1 deletion pybind/core/pyutils.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@

#pragma once

// openpiv
#include "core/image.h"

// std
#include <array>

#include <vector>

template <size_t N>
using char_array = std::array<char, N>;
Expand Down Expand Up @@ -127,3 +130,47 @@ static_assert(pixel_type_trait<g, uint8_t>::name() == "g_u8");
static_assert(pixel_type_trait<rgba, uint16_t>::name() == "rgba_u16");
static_assert(pixel_type_trait<yuva, uint32_t>::name() == "yuva_u32");
static_assert(pixel_type_trait<complex, double>::name() == "c_f");


template <template <typename> class I,
template <typename> class P,
typename U>
struct image_type_trait
{
template <size_t N=64>
static constexpr char_array<N> name()
{
return cat<N>(to_array<8>("image"), pixel_type_trait<P, U>::name());
}

/// this returns strides in matrix convention
static std::vector<size_t> strides(const I<P<U>>& im)
{
const auto [column_stride, row_stride] = im.stride();
if constexpr (are_any_equal_v<P<U>, rgba<U>, yuva<U>>)
return { row_stride, column_stride, 4 };
else if constexpr (are_any_equal_v<P<U>, complex<U>>)
return { row_stride, column_stride, 2 };
else
return { row_stride, column_stride };
}

/// this returns dimensions in matrix convention
static std::vector<size_t> dimensions(const I<P<U>>& im)
{
if constexpr (are_any_equal_v<P<U>, rgba<U>, yuva<U>>)
return { im.height(), im.width(), 4 };
else if constexpr (are_any_equal_v<P<U>, complex<U>>)
return { im.height(), im.width(), 2 };
else
return { im.height(), im.width() };
}

};

// test
static_assert(image_type_trait<image, g, uint8_t>::name() == "image_g_u8");
static_assert(image_type_trait<image, rgba, uint16_t>::name() == "image_rgba_u16");
static_assert(image_type_trait<image, yuva, uint32_t>::name() == "image_yuva_u32");
static_assert(image_type_trait<image, complex, double>::name() == "image_c_f");

0 comments on commit 88d4c56

Please sign in to comment.