Effortless loading of images, audio files and NumPy npz files!

In [1]:
#include <string>
#include <fstream>

#include "xwidgets/ximage.hpp"
#include "xwidgets/xslider.hpp"

#include "xtensor/xview.hpp"
#include "xtensor/xio.hpp"

#include "xtensor-io/ximage.hpp"
#include "xtensor-io/xaudio.hpp"
#include "xtensor-io/xnpz.hpp"

#include "xtl/xbase64.hpp"

#include "xcpp/xdisplay.hpp"

In [2]:
std::vector<char> read_file(const char* filename)
{
    std::basic_ifstream<char> file(filename, std::ios::binary);
    return std::vector<char>((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
}

In [3]:
template <class E>
std::vector<char> to_png_buffer(const xt::xexpression<E>& e)
{
    const char* temp_filename = "/tmp/xio_image.png";
    xt::dump_image(temp_filename, e);
    return read_file(temp_filename);
}

Loading an image

In the following an image is loaded from the file system, and then displayed using the above helper function. The slider can be used to make the lightsaber more-or-less xtensor-green!


In [4]:
auto lightsaber = xt::load_image("images/saber.png");

In [5]:
xw::image ls_image;
ls_image.value = to_png_buffer(lightsaber);
ls_image


Out[5]:

In [6]:
xt::xtensor<double, 3> lightsaber_modified;

In [7]:
template <class E>
void modify_image(xt::xexpression<E>& e, double value)
{
    lightsaber_modified = e.derived_cast();
    double inc = value * 0.2;
    xt::xtensor<double, 1> filter = {1. - inc, 1. + inc, 1. - inc};
    lightsaber_modified *= filter;
    ls_image.value = to_png_buffer(lightsaber_modified);
}

In [8]:
xw::slider<double> slider;
slider.max = 5;
slider.value = 2;
slider.continuous_update = false;
slider.display();

XOBSERVE(slider, value, [](const auto& s) {
    modify_image(lightsaber, s.value());
});


Loading Audio

In the next example a WAV file is loaded from the file system. The load_audio function returns a tuple, where the first value is the samplerate and the second value is an xarray holding the sound data.


In [ ]:
auto swing = xt::load_audio("audio/lightsaber_swing.wav");

In [ ]:
int sample_rate = std::get<0>(swing);
auto audio_data = std::get<1>(swing);

In [ ]:
template <class E>
auto player(const xt::xexpression<E>& e, int sample_rate, xeus::xguid id = xeus::xguid(), bool update = false)
{
    using namespace std::string_literals;
    xt::dump_audio("/tmp/xio_audio.wav", e, sample_rate);
    std::ifstream fin("/tmp/xio_audio.wav", std::ios::binary);
    std::stringstream buffer;
    buffer << fin.rdbuf();

    xeus::xjson mime;
    mime["text/html"] = std::string("<audio autoplay controls loop src=\"data:audio/wav;base64,") + 
                        xtl::base64encode(buffer.str()) + "\"/>";
    xeus::xjson transient;

    if (update)
    {
        transient["display_id"] = id;
        xeus::get_interpreter().update_display_data(
            std::move(mime),
            xeus::xjson::object(),
            std::move(transient));
        return id;
    }
    else
    {
        id = xeus::new_xguid();
        transient["display_id"] = id;
        xeus::get_interpreter().display_data(
            std::move(mime),
            xeus::xjson::object(),
            std::move(transient));
        return id;
    }
}

In [ ]:
auto audio_id = player(std::get<1>(swing), sample_rate);

In [ ]:
xw::slider<int> samplerate_slider;
samplerate_slider.max = 50000;
samplerate_slider.value = sample_rate;
samplerate_slider.continuous_update = false;
samplerate_slider.display();

XOBSERVE(samplerate_slider, value, [](const auto& s) {
    player(std::get<1>(swing), s.value(), audio_id, true);
});

In [ ]: