Creating and loading images
Regular 2D images from scratch
image2d<T>
is the most-used image type representing images defined on a 2D grid. It is a template
class, where the parameter T can be replaced by the type of value to store. For instance, if it is a grayscale image
with values encoded on 8-bits unisgned integers, T will be uint8_t. For RGB-8 images, T is mln::rgb8
. Any
regular (foundamental) type can be used, fixed-size scalar and floating-point types are already defined in C++ in the
<cstdint> header. The template parameter T is that we call the
value type (every image has a value type, be it static or dynamic)
An image might be created from a set of values (this is generally used only for testing an algorithm). For instance, in the following code, a 2 × 3 2D image is created with values from 1 to 6:
#include <mln/core/image/ndimage.hpp>
mln::image2d<uint8_t> f = {{1,2,3}, {4,5,6}};
It is generally more commom to create a 2D image from its size, using its width and its height to reserve space. Note that values are (generally) undefined:
// Create a 800x600 2D images
mln::image2d<uint8_t> f(800, 600);
A last parameter allows to customize the initialization of an image. It can be used to initialize an image with a custom value, e.g. the grayscale value 128:
// Create a 800x600 2D images
mln::image2d<uint8_t> f(800, 600, {.init_value = uint8_t(128)})
Finally a 2D image may not start at location (0,0). For instance when want to work a sub-regions of an image, the
location of the origin has moved. Every image is a tied to a domain, which is a box2d
for 2D images.
One can initialize an image from a domain of a pair (width, height):
// A roi (x=50,y=50,w=100,h=100)
mln::box2d roi = {{50,50}, {150,150}};
mln::image2d<uint8_t> f(roi);
Regular ND images
The class image2d
is generalized in any dimension (image1d
, image3d
and so
on). Actually, they are aliases over the type (ndimage<T, N>
where the
dimension is fixed).
Thus you can create 3D-images from a initializer-lists:
#include <mln/core/image/ndimage.hpp>
// A 2x2x3 3D-image
mln::image2d<uint8_t> f = {
{{1,2,3}, {4,5,6}},
{{7,8,9}, {10,11,12}}
};
From a triplet (width,height,depth):
// Create a 800x600 2D images
mln::image2d<uint8_t> f(128, 128, 128);
From a box3d
domain:
// A roi (x=50,y=50,z=50,w=100,h=100,d=100)
mln::box2d roi = {{50,50,50}, {150,150,150}};
mln::image3d<uint8_t> f(roi);
Loading and saving an image
An image can be loaded from a file. It actually relies on the freeimage library to handle most file formats:
#include <mln/core/image/ndimage.hpp>
#include <mln/io/imread.hpp>
{
mln::image2d<uint8_t> f;
mln::io::imread("input.pgm", f);
}
{
mln::image2d<uint8_t> f = { {1,2,3}, {4,5,6} };
mln::io::imsave(f, "out.pgm");
}
Images from existing data
In your application, would will mostly want to use algorithms from many libraries that do not share the image types. As
soon as an image is encoded as C raw-buffer of data, you will be able to exchange images from/to pylene using
__ndbuffer_image::from_buffer()
.
uint8_t data[] = {255, 0, 0, 255};
int dims[] = {2, 2};
auto input = mln::image2d<uint8_t>::from_buffer(data, dims);
And you can access the Pylene internal buffer with buffer