From b26f2d2a15d652427dfd6ef1542343ecbfe6f620 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Mon, 24 Jan 2022 22:15:55 +0000 Subject: [PATCH] Refactor save_image into save_image_impl finally done!! Signed-off-by: Omar Shrit --- src/mlpack/core/data/CMakeLists.txt | 1 + src/mlpack/core/data/load_image.hpp | 2 +- src/mlpack/core/data/load_image_impl.hpp | 6 +- src/mlpack/core/data/load_impl.hpp | 3 +- src/mlpack/core/data/save.hpp | 41 +---- src/mlpack/core/data/save_image.hpp | 165 +++++-------------- src/mlpack/core/data/save_image_impl.hpp | 195 +++++++++++++++++++++++ src/mlpack/core/data/save_impl.hpp | 60 ------- 8 files changed, 247 insertions(+), 226 deletions(-) create mode 100644 src/mlpack/core/data/save_image_impl.hpp diff --git a/src/mlpack/core/data/CMakeLists.txt b/src/mlpack/core/data/CMakeLists.txt index a5c0438bf7..0b83444c00 100644 --- a/src/mlpack/core/data/CMakeLists.txt +++ b/src/mlpack/core/data/CMakeLists.txt @@ -25,6 +25,7 @@ set(SOURCES save.hpp save_impl.hpp save_image.hpp + save_image_impl.hpp split_data.hpp string_algorithms.hpp imputer.hpp diff --git a/src/mlpack/core/data/load_image.hpp b/src/mlpack/core/data/load_image.hpp index fb362ae955..36e4015302 100644 --- a/src/mlpack/core/data/load_image.hpp +++ b/src/mlpack/core/data/load_image.hpp @@ -23,7 +23,7 @@ #define STB_IMAGE_IMPLEMENTATION #include -#endif +#endif // HAS_STB namespace mlpack { namespace data { diff --git a/src/mlpack/core/data/load_image_impl.hpp b/src/mlpack/core/data/load_image_impl.hpp index 3ebcade286..57b9d7b6fd 100644 --- a/src/mlpack/core/data/load_image_impl.hpp +++ b/src/mlpack/core/data/load_image_impl.hpp @@ -2,7 +2,7 @@ * @file core/data/load_image_impl.hpp * @author Mehul Kumar Nirala * - * An image loading utility implementation. + * An image loading utility implementation via STB. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the @@ -188,7 +188,7 @@ inline bool LoadImage(const std::string& /* filename */, #endif -} -} +} // namespace data +} // namespace mlpack #endif diff --git a/src/mlpack/core/data/load_impl.hpp b/src/mlpack/core/data/load_impl.hpp index 226960a7e0..03993716db 100644 --- a/src/mlpack/core/data/load_impl.hpp +++ b/src/mlpack/core/data/load_impl.hpp @@ -16,13 +16,12 @@ // In case it hasn't already been included. #include "load.hpp" -#include #include +#include #include #include "extension.hpp" #include "detect_file_type.hpp" - #include "string_algorithms.hpp" namespace mlpack { diff --git a/src/mlpack/core/data/save.hpp b/src/mlpack/core/data/save.hpp index 793cf89abe..2faf180618 100644 --- a/src/mlpack/core/data/save.hpp +++ b/src/mlpack/core/data/save.hpp @@ -14,6 +14,7 @@ #ifndef MLPACK_CORE_DATA_SAVE_HPP #define MLPACK_CORE_DATA_SAVE_HPP +#include #include #include // Includes Armadillo. #include @@ -21,6 +22,7 @@ #include "format.hpp" #include "image_info.hpp" #include "detect_file_type.hpp" +#include "save_image.hpp" namespace mlpack { namespace data /** Functions to load and save matrices. */ { @@ -130,49 +132,10 @@ bool Save(const std::string& filename, const bool fatal = false, format f = format::autodetect); -/** - * 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). - * @return Boolean value indicating success or failure of load. - */ -template -bool Save(const std::string& filename, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal = false); - -/** - * 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). - * @return Boolean value indicating success or failure of load. - */ -template -bool Save(const std::vector& files, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal = false); - -/** - * Helper function to save files. Implementation in save_image.hpp. - */ -inline bool SaveImage(const std::string& filename, - arma::Mat& image, - ImageInfo& info, - const bool fatal = false); - } // namespace data } // namespace mlpack // Include implementation. #include "save_impl.hpp" -#include "save_image.hpp" #endif diff --git a/src/mlpack/core/data/save_image.hpp b/src/mlpack/core/data/save_image.hpp index c98e38daf3..40a9186cdc 100644 --- a/src/mlpack/core/data/save_image.hpp +++ b/src/mlpack/core/data/save_image.hpp @@ -1,8 +1,8 @@ /** - * @file core/data/save_image.hpp - * @author Mehul Kumar Nirala + * @file core/data/save_image_impl.hpp + * @author Ryan Curtin * - * Implementation of image saving functionality via STB. + * Implementation of save functionality. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the @@ -12,138 +12,61 @@ #ifndef MLPACK_CORE_DATA_SAVE_IMAGE_HPP #define MLPACK_CORE_DATA_SAVE_IMAGE_HPP -#include "save.hpp" +#include "image_info.hpp" #ifdef HAS_STB -// Include STB functions. Note that we include the implementations, too, and -// all functions will be marked as static. #define STB_IMAGE_WRITE_STATIC #define STB_IMAGE_WRITE_IMPLEMENTATION #include +#endif // HAS_STB + namespace mlpack { namespace data { +/** + * 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). + * @return Boolean value indicating success or failure of load. + */ +template +bool Save(const std::string& filename, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal = false); + +/** + * 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). + * @return Boolean value indicating success or failure of load. + */ +template +bool Save(const std::vector& files, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal = false); + +/** + * Helper function to save files. Implementation in save_image.hpp. + */ inline bool SaveImage(const std::string& filename, arma::Mat& image, ImageInfo& info, - const bool fatal) -{ - // Check to see if the file type is supported. - if (!ImageFormatSupported(filename, true)) - { - std::ostringstream oss; - oss << "Save(): file type " << Extension(filename) << " not supported.\n"; - oss << "Currently image saving supports "; - for (auto extension : SaveFileTypes()) - oss << ", " << extension; - oss << "." << std::endl; + const bool fatal = false); - if (fatal) - { - Log::Fatal << oss.str(); - } - else - { - Log::Warn << oss.str(); - } +} //namespace data +} //namespace mlpack - return false; - } - - // Ensure the shape of the matrix is correct. - if (image.n_cols > 1) - { - Log::Warn << "Save(): given input image matrix contains more than 1 image." - << std::endl; - Log::Warn << "Only the first image will be saved!" << std::endl; - } - - if (info.Width() * info.Height() * info.Channels() != image.n_elem) - { - Log::Fatal << "data::Save(): The given image dimensions do not match the " - << "dimensions of the matrix to be saved!" << std::endl; - } - - bool status = false; - unsigned char* imageMem = image.memptr(); - - if ("png" == Extension(filename)) - { - status = stbi_write_png(filename.c_str(), info.Width(), info.Height(), - info.Channels(), imageMem, info.Width() * info.Channels()); - } - else if ("bmp" == Extension(filename)) - { - status = stbi_write_bmp(filename.c_str(), info.Width(), info.Height(), - info.Channels(), imageMem); - } - else if ("tga" == Extension(filename)) - { - status = stbi_write_tga(filename.c_str(), info.Width(), info.Height(), - info.Channels(), imageMem); - } - else if ("hdr" == Extension(filename)) - { - // We'll have to convert to float... - arma::fmat tmpImage = arma::conv_to::from(image); - status = stbi_write_hdr(filename.c_str(), info.Width(), info.Height(), - info.Channels(), tmpImage.memptr()); - } - else if ("jpg" == Extension(filename)) - { - status = stbi_write_jpg(filename.c_str(), info.Width(), info.Height(), - info.Channels(), imageMem, info.Quality()); - } - - if (!status) - { - if (fatal) - { - Log::Fatal << "Save(): error saving image to '" << filename << "'." - << std::endl; - } - else - { - Log::Warn << "Save(): error saving image to '" << filename << "'." - << std::endl; - } - } - - return status; -} - -} // namespace data -} // namespace mlpack - -#else - -namespace mlpack { -namespace data { - -inline bool SaveImage(const std::string& /* filename */, - arma::Mat& /* image */, - ImageInfo& /* info */, - const bool fatal) -{ - if (fatal) - { - Log::Fatal << "Save(): mlpack was not compiled with STB support, so images " - << "cannot be saved!" << std::endl; - } - else - { - Log::Warn << "Save(): mlpack was not compiled with STB support, so images " - << "cannot be saved!" << std::endl; - } - - return false; -} - -} // namespace data -} // namespace mlpack - -#endif +// Include implementation of Save() for images. +#include "save_image_impl.hpp" #endif diff --git a/src/mlpack/core/data/save_image_impl.hpp b/src/mlpack/core/data/save_image_impl.hpp new file mode 100644 index 0000000000..3766593418 --- /dev/null +++ b/src/mlpack/core/data/save_image_impl.hpp @@ -0,0 +1,195 @@ +/** + * @file core/data/save_image_impl.hpp + * @author Mehul Kumar Nirala + * + * Implementation of image saving functionality via STB. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_CORE_DATA_SAVE_IMAGE_IMPL_HPP +#define MLPACK_CORE_DATA_SAVE_IMAGE_IMPL_HPP + +// In case it hasn't been included yet. +#include "save_image.hpp" +#include "image_info.hpp" + +namespace mlpack { +namespace data { + +/** + * Save the given image to the given filename. + * + * @param filename Filename to save to. + * @param matrix Matrix containing image to be saved. + * @param info Information about the image (width/height/channels/etc.). + * @param fatal Whether an exception should be thrown on save failure. + */ +template +bool Save(const std::string& filename, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal) +{ + arma::Mat tmpMatrix = + arma::conv_to>::from(matrix); + + return SaveImage(filename, tmpMatrix, info, fatal); +} + +// Image saving API for multiple files. +template +bool Save(const std::vector& files, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal) +{ + if (files.size() == 0) + { + if (fatal) + { + Log::Fatal << "Save(): vector of image files is empty; nothing to save." + << std::endl; + } + else + { + Log::Warn << "Save(): vector of image files is empty; nothing to save." + << std::endl; + } + + return false; + } + + arma::Mat img; + bool status = true; + + for (size_t i = 0; i < files.size() ; ++i) + { + arma::Mat colImg(matrix.colptr(i), matrix.n_rows, 1, + false, true); + status &= Save(files[i], colImg, info, fatal); + } + + return status; +} + +#ifdef HAS_STB + +inline bool SaveImage(const std::string& filename, + arma::Mat& image, + ImageInfo& info, + const bool fatal) +{ + // Check to see if the file type is supported. + if (!ImageFormatSupported(filename, true)) + { + std::ostringstream oss; + oss << "Save(): file type " << Extension(filename) << " not supported.\n"; + oss << "Currently image saving supports "; + for (auto extension : SaveFileTypes()) + oss << ", " << extension; + oss << "." << std::endl; + + if (fatal) + { + Log::Fatal << oss.str(); + } + else + { + Log::Warn << oss.str(); + } + + return false; + } + + // Ensure the shape of the matrix is correct. + if (image.n_cols > 1) + { + Log::Warn << "Save(): given input image matrix contains more than 1 image." + << std::endl; + Log::Warn << "Only the first image will be saved!" << std::endl; + } + + if (info.Width() * info.Height() * info.Channels() != image.n_elem) + { + Log::Fatal << "data::Save(): The given image dimensions do not match the " + << "dimensions of the matrix to be saved!" << std::endl; + } + + bool status = false; + unsigned char* imageMem = image.memptr(); + + if ("png" == Extension(filename)) + { + status = stbi_write_png(filename.c_str(), info.Width(), info.Height(), + info.Channels(), imageMem, info.Width() * info.Channels()); + } + else if ("bmp" == Extension(filename)) + { + status = stbi_write_bmp(filename.c_str(), info.Width(), info.Height(), + info.Channels(), imageMem); + } + else if ("tga" == Extension(filename)) + { + status = stbi_write_tga(filename.c_str(), info.Width(), info.Height(), + info.Channels(), imageMem); + } + else if ("hdr" == Extension(filename)) + { + // We'll have to convert to float... + arma::fmat tmpImage = arma::conv_to::from(image); + status = stbi_write_hdr(filename.c_str(), info.Width(), info.Height(), + info.Channels(), tmpImage.memptr()); + } + else if ("jpg" == Extension(filename)) + { + status = stbi_write_jpg(filename.c_str(), info.Width(), info.Height(), + info.Channels(), imageMem, info.Quality()); + } + + if (!status) + { + if (fatal) + { + Log::Fatal << "Save(): error saving image to '" << filename << "'." + << std::endl; + } + else + { + Log::Warn << "Save(): error saving image to '" << filename << "'." + << std::endl; + } + } + + return status; +} + +#else // HAS_STB + +inline bool SaveImage(const std::string& /* filename */, + arma::Mat& /* image */, + ImageInfo& /* info */, + const bool fatal) +{ + if (fatal) + { + Log::Fatal << "Save(): mlpack was not compiled with STB support, so images " + << "cannot be saved!" << std::endl; + } + else + { + Log::Warn << "Save(): mlpack was not compiled with STB support, so images " + << "cannot be saved!" << std::endl; + } + + return false; +} + +#endif + +} // namespace data +} // namespace mlpack + +#endif diff --git a/src/mlpack/core/data/save_impl.hpp b/src/mlpack/core/data/save_impl.hpp index 4542b1c6e7..2d3c92e9ff 100644 --- a/src/mlpack/core/data/save_impl.hpp +++ b/src/mlpack/core/data/save_impl.hpp @@ -16,10 +16,6 @@ #include "save.hpp" #include "extension.hpp" -#include -#include -#include - namespace mlpack { namespace data { @@ -344,62 +340,6 @@ bool Save(const std::string& filename, } } -/** - * Save the given image to the given filename. - * - * @param filename Filename to save to. - * @param matrix Matrix containing image to be saved. - * @param info Information about the image (width/height/channels/etc.). - * @param fatal Whether an exception should be thrown on save failure. - */ -template -bool Save(const std::string& filename, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal) -{ - arma::Mat tmpMatrix = - arma::conv_to>::from(matrix); - - return SaveImage(filename, tmpMatrix, info, fatal); -} - -// Image saving API for multiple files. -template -bool Save(const std::vector& files, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal) -{ - if (files.size() == 0) - { - if (fatal) - { - Log::Fatal << "Save(): vector of image files is empty; nothing to save." - << std::endl; - } - else - { - Log::Warn << "Save(): vector of image files is empty; nothing to save." - << std::endl; - } - - return false; - } - - arma::Mat img; - bool status = true; - - for (size_t i = 0; i < files.size() ; ++i) - { - arma::Mat colImg(matrix.colptr(i), matrix.n_rows, 1, - false, true); - status &= Save(files[i], colImg, info, fatal); - } - - return status; -} - } // namespace data } // namespace mlpack