/*!
@file image.txt
@author Mehul Kumar Nirala
@brief Tutorial for how to load and save images in mlpack.

@page imagetutorial Image Utilities tutorial

@section intro_imagetut Introduction

Image datasets are becoming increasingly popular in deep learning.

mlpack's image saving/loading functionality is based on [stb/](https://github.com/nothings/stb).

@section toc_imagetut Table of Contents

This tutorial is split into the following sections:

 - \ref intro_imagetut
 - \ref toc_imagetut
 - \ref model_api_imagetut
 - \ref imageinfo_api_imagetut
 - \ref load_api_imagetut
 - \ref save_api_imagetut

@section model_api_imagetut Model API

Image utilities supports loading and saving of images.

It supports filetypes "jpg", "png", "tga","bmp", "psd", "gif", "hdr", "pic", "pnm" for loading and "jpg", "png", "tga", "bmp", "hdr" for saving.

The datatype associated is unsigned char to support RGB values in the range 1-255. To feed data into the network typecast of `arma::Mat` may be required. Images are stored in matrix as (width * height * channels, NumberOfImages). Therefore imageMatrix.col(0) would be the first image if images are loaded in imageMatrix.

@section imageinfo_api_imagetut ImageInfo

ImageInfo class contains the metadata of the images.
@code
  /**
   * Instantiate the ImageInfo object with the image width, height, channels.
   *
   * @param width Image width.
   * @param height Image height.
   * @param channels number of channels in the image.
   */
  ImageInfo(const size_t width,
            const size_t height,
            const size_t channels);
@endcode
Other public memebers include:
  - flipVertical Flip the image vertical upon loading.
  - quality Compression of the image if saved as jpg (0-100).

@section load_api_imagetut Load


Standalone loading of images.
@code
  /**
   * Load the image file into the given matrix.
   *
   * @param filename Name of the image file.
   * @param matrix Matrix to load the image into.
   * @param info An object of ImageInfo class.
   * @param fatal If an error should be reported as fatal (default false).
   * @param transpose If true, transpose the matrix after loading.
   * @return Boolean value indicating success or failure of load.
   */
   template<typename eT>
   bool Load(const std::string& filename,
             arma::Mat<eT>& matrix,
             ImageInfo& info,
             const bool fatal,
             const bool transpose);
@endcode

Loading a test image. It also fills up the ImageInfo class object.
@code
data::ImageInfo info;
data::Load("test_image.png", matrix, info, false, true);
@endcode

ImageInfo requires height, width, number of channels of the image.

@code
size_t height = 64, width = 64, channels = 1;
data::ImageInfo info(width, height, channels);
@endcode

More than one image can be loaded into the same matrix.

Loading multiple images:

@code
  /**
   * Load the image file into the given matrix.
   *
   * @param files A vector consisting of filenames.
   * @param matrix Matrix to save the image from.
   * @param info An object of ImageInfo class.
   * @param fatal If an error should be reported as fatal (default false).
   * @param transpose If true, transpose the matrix after loading.
   * @return Boolean value indicating success or failure of load.
   */
   template<typename eT>
   bool Load(const std::vector<std::string>& files,
             arma::Mat<eT>& matrix,
             ImageInfo& info,
             const bool fatal,
             const bool transpose);
@endcode

@code
  data::ImageInfo info;
  std::vector<std::string>> files{"test_image1.bmp","test_image2.bmp"};
  data::load(files, matrix, info, false, true);
@endcode

@section save_api_imagetut Save

Save images expects a matrix of type unsigned char in the form (width * height * channels, NumberOfImages).
Just like load it can be used to save one image or multiple images. Besides image data it also expects the shape of the image as input (width, height, channels).

Saving one image:

@code
  /**
   * Save the image file from the given matrix.
   *
   * @param filename Name of the image file.
   * @param matrix Matrix to save the image from.
   * @param info An object of ImageInfo class.
   * @param fatal If an error should be reported as fatal (default false).
   * @param transpose If true, transpose the matrix after loading.
   * @return Boolean value indicating success or failure of load.
   */
   template<typename eT>
   bool Save(const std::string& filename,
             arma::Mat<eT>& matrix,
             ImageInfo& info,
             const bool fatal,
             const bool transpose);
@endcode

@code
  data::ImageInfo info;
  info.width = info.height = 25;
  info.channels = 3;
  info.quality = 90;
  data::Save("test_image.bmp", matrix, info, false, true);
@endcode

If the matrix contains more than one image, only the first one is saved.

Saving multiple images:

@code
  /**
   * Save the image file from the given matrix.
   *
   * @param files A vector consisting of filenames.
   * @param matrix Matrix to save the image from.
   * @param info An object of ImageInfo class.
   * @param fatal If an error should be reported as fatal (default false).
   * @param transpose If true, transpose the matrix after loading.
   * @return Boolean value indicating success or failure of load.
   */
   template<typename eT>
   bool Save(const std::vector<std::string>& files,
             arma::Mat<eT>& matrix,
             ImageInfo& info,
             const bool fatal,
             const bool transpose);
@endcode

@code
  data::ImageInfo info;
  info.width = info.height = 25;
  info.channels = 3;
  info.quality = 90;
  std::vector<std::string>> files{"test_image1.bmp", "test_image2.bmp"};
  data::Save(files, matrix, info, false, true);
@endcode

Multiple images are saved according to the vector of filenames specified.

*/
