-
Notifications
You must be signed in to change notification settings - Fork 27
/
ximage.hpp
97 lines (83 loc) · 3.17 KB
/
ximage.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <stdexcept>
#include <string>
#include "xtensor/xarray.hpp"
#include "xtensor/xeval.hpp"
#include "xtensor_io_config.hpp"
#ifdef __CLING__
#pragma clang diagnostic push
// silencing warnings from OpenEXR 2.2.0 / OpenImageIO
#pragma clang diagnostic ignored "-Wdeprecated-register"
#pragma cling load("OpenImageIO")
#endif
#include <OpenImageIO/imageio.h>
#ifdef __CLING__
#pragma clang diagnostic pop
#endif
namespace xt
{
/**
* Load an image from file at filename.
* Storage format is deduced from file ending.
*
* @param filename The path of the file to load
*
* @return xarray with image contents. The shape of the xarray
* is ``WIDTH x HEIGHT x CHANNELS`` of the loaded image, where
* ``CHANNELS`` are ordered in standard ``R G B (A)``.
*/
template <class T = unsigned char>
xarray<T> load_image(std::string filename)
{
// TODO handle types better
OIIO::ImageInput* in = OIIO::ImageInput::open(filename);
if (!in)
{
// something went wrong
throw std::runtime_error("Error reading image.");
}
const OIIO::ImageSpec& spec = in->spec();
int xres = spec.width;
int yres = spec.height;
int channels = spec.nchannels;
// allocate memory
auto image = xarray<T>::from_shape({static_cast<std::size_t>(spec.width),
static_cast<std::size_t>(spec.height),
static_cast<std::size_t>(spec.nchannels)});
in->read_image(OIIO::TypeDesc::UINT8, image.raw_data());
in->close();
OIIO::ImageInput::destroy(in);
return image;
}
/**
* Save image to disk.
* The desired image format is deduced from ``filename``.
* Supported formats are those supported by OpenImageIO.
* Most common formats are supported (jpg, png, gif, bmp, tiff).
*
* @param filename The path to the desired file
* @param data Image data
* @param quality If saving in a compressed format such as JPEG, setting the quality
* will select how strong the compression will reduce the image quality.
* Quality is an integer from 100 (best image quality, less compression)
* to 0 (worst image quality, low filesize).
*/
template <class E>
void dump_image(std::string filename, const xexpression<E>& data, int quality = 90)
{
auto&& ex = eval(data.derived_cast());
OIIO::ImageOutput* out = OIIO::ImageOutput::create(filename);
if (!out)
{
// something went wrong
throw std::runtime_error("Error opening file to write image.");
}
OIIO::ImageSpec spec(static_cast<int>(ex.shape()[0]),
static_cast<int>(ex.shape()[1]),
static_cast<int>(ex.shape()[2]), OIIO::TypeDesc::UINT8);
spec.attribute("CompressionQuality", quality);
out->open(filename, spec);
out->write_image(OIIO::TypeDesc::UINT8, ex.raw_data());
out->close();
OIIO::ImageOutput::destroy(out);
}
}