Commit 175045c9 authored by norbertf's avatar norbertf
Browse files

improved CLI / does not overwrite src / more scaling options

parent 0e49edf9
......@@ -44,20 +44,20 @@ protected:
memcpy(target.data, src.data(), src.height() * src.width());
return target;
}
public:
static Image resize_to_height(const Image& src, size_t target_height, const ResizeInterpolationType interpolation = ResizeInterpolationType::CUBIC){
static void check_src(const Image& src) {
if (src.depth != 1){
throw std::runtime_error("Image to resize has more than 1 channel");
}
auto img = to_cimg(src);
if (src.height <= 0 || src.width <= 0){
// uhm,
throw std::runtime_error("Cannot resize an image with zero dimensions");
}
}
public:
static Image resize_to(const Image& src, int target_width, int target_height, const ResizeInterpolationType interpolation = ResizeInterpolationType::CUBIC){
check_src(src);
double scaling_factor = target_height / (double) src.height;
int target_width = static_cast<int> (src.width * scaling_factor + 0.5);
auto img = to_cimg(src);
const cimage& resized = img.resize(target_width, target_height,-100,-100,(int)interpolation);
if(target_width != resized.width() || target_height != resized.height()){
......@@ -65,6 +65,30 @@ public:
}
return from_cimg(resized);
}
static Image resize_to_height(const Image& src, size_t target_height, const ResizeInterpolationType interpolation = ResizeInterpolationType::CUBIC){
check_src(src);
double scaling_factor = target_height / (double) src.height;
int target_width = static_cast<int> (src.width * scaling_factor + 0.5);
return resize_to(src, target_width, target_height, interpolation);
}
static Image resize_to_width(const Image& src, size_t target_width, const ResizeInterpolationType interpolation = ResizeInterpolationType::CUBIC){
check_src(src);
double scaling_factor = target_width / (double) src.width;
int target_height = static_cast<int> (src.height * scaling_factor + 0.5);
return resize_to(src, target_width, target_height, interpolation);
}
static Image resize_to_bbox(const Image& src, const size_t max_width, const size_t max_height, const ResizeInterpolationType interpolation = ResizeInterpolationType::CUBIC){
check_src(src);
if (src.height <= max_height && src.width <= max_width){
return src;
}
double scaling_factor = std::min(max_width / (double) src.width, max_height / (double) src.height);
int target_width = static_cast<int> (src.width * scaling_factor + 0.5);
int target_height = static_cast<int> (src.height * scaling_factor + 0.5);
return resize_to(src, target_width, target_height, interpolation);
}
};
}
......@@ -20,6 +20,7 @@
#include "../Doxa/Resize.hpp"
#include <filesystem>
#include <ostream>
#include <utility>
#include <string_view>
......@@ -82,6 +83,9 @@ struct Args{
int limit_height = 0;
bool limit_height_given = false;
int limit_width = 0;
bool limit_width_given = false;
bool nearest_neighbor_given = false;
bool use_imagemagick_loader = false;
......@@ -91,21 +95,28 @@ struct Args{
int Help(const int returnValue)
{
cout << endl
<< "BinaryImageConverter v2.0" << endl
<< "binzr. Image Binarizer Toolkit" << endl
<< endl
<< "This application will convert a color or greyscale image into a black and white binary image." << endl
<< "Supported source file formats are: jpg, png, bmp, but more files can be loaded" << endl
<< "by using imagemagick's convert command (--magick), but this is unsafe [use with care]." << endl
<< endl
<< "Usage: binzr --source <image location> [-<algorithm>] [--w <window size>] [--k <k value>] " << endl
<< "Usage:" << endl
<< " binzr --source <image location> [-<algorithm>] [--w <window size>] [--k <k value>] [OPTIONS]" << endl
<< endl
<< "Algorithms: otsu, bernsen, niblack, sauvola, wolf, nick, gatos, su, trsingh, bataineh, wan, isauvola, greyscale, normgreyscale" << endl
<< endl
<< "Other options:" << endl
<< "--limit_height MAX_H --subdirs -o output_file --output_dir directort --magick" << endl
<< " --limit_height MAX_H Rescale Images to a maximum height of MAX_H" << endl
<< " --limit_width MAX_W Rescale Images to a maximum width of MAX_W" << endl
<< " --limit_ls MAX_LS Limit longer side to a maximum of MAX_LS" << endl
<< " --subdirs If multiple methods are specified, write the output in sub-directories" << endl
<< " -o output_file Specify output file (only works if 1 method is given)" << endl
<< " --output_dir DIR Write binarized images with as filename.png to DIR" << endl
<< " --magick Use ImageMagick for decoding input images (more file formats)" << endl
<< endl
<< "Multiple algorithms can be specified at once. Defaults: w = 75, k = 0.2 (Nick's k = -0.2), g = 60" << endl
<< "Example: BinaryImageConverter.exe --source c:\\image.pam -wolf -sauvola --w 23 --k 0.15" << endl
<< "Output: c:\\image-Wolf.pam, c:\\image-Sauvola.pam" << endl
<< "Example: binzr --source image.png -wolf -sauvola --w 23 --k 0.15 --output_dir out --subdirs" << endl
<< endl
<< "Note: Gatos is only partially implemented and can take in an optional glyph size, [--g <glyph size>]." << endl
<< "Note: Su will use window size, which should be set to the stroke width. Default: 10" << endl
......@@ -209,6 +220,18 @@ Args parseArgs(int argc, char* argv[]){
args.limit_height = std::stoi(argv[idx]);
args.limit_height_given = true;
}
else if (arg.compare("--limit_width") == 0){
if (++idx >= argc) Help(0);
args.limit_width = std::stoi(argv[idx]);
args.limit_width_given = true;
}
else if (arg.compare("--limit_ls") == 0){
if (++idx >= argc) Help(0);
args.limit_width = std::stoi(argv[idx]);
args.limit_height = std::stoi(argv[idx]);
args.limit_width_given = true;
args.limit_height_given = true;
}
else if(arg.compare("--nearest_neighbor") == 0){
args.nearest_neighbor_given = true;
}
......@@ -248,7 +271,7 @@ Args parseArgs(int argc, char* argv[]){
Help(1);
}
if (count_requested_methods > 1 && (args.output_directory_given && ! args.put_in_subdirs)){
cerr << "Cannot specify multiple methode with output_directory but without --subdirs" << endl;
cerr << "Cannot specify multiple method with output_directory but without --subdirs" << endl;
Help(1);
}
if (args.put_in_subdirs && args.output_file_given) {
......@@ -259,6 +282,10 @@ Args parseArgs(int argc, char* argv[]){
cerr << "Cannot specify --output_dir and -o simultanously." << endl;
Help(1);
}
if (! (args.output_directory_given || args.output_file_given)){
cerr << "Must specify either output directory or output filename" << endl;
Help(1);
}
return args;
}
......@@ -274,10 +301,19 @@ int main(int argc, char* argv[])
const Parameters greyscale_params(ParameterMap({ { "grayscale", GrayscaleConversion::BT709 } }));
Image _loaded = GenericImageReader::Read(args.source, greyscale_params, args.use_imagemagick_loader);
// resize this image, if requested
if (args.limit_height_given && args.limit_height < _loaded.height){
const auto interpolation = args.nearest_neighbor_given ? ResizeInterpolationType::NEAREST_NEIGHBOR : ResizeInterpolationType::CUBIC;
const auto interpolation = args.nearest_neighbor_given ? ResizeInterpolationType::NEAREST_NEIGHBOR : ResizeInterpolationType::CUBIC;
if (args.limit_height_given && args.limit_width_given){
if(_loaded.width > args.limit_width || _loaded.height > args.limit_height){
_loaded = Doxa::ImageResize::resize_to_bbox(_loaded,args.limit_width, args.limit_height, interpolation);
}
}
else if (args.limit_height_given && args.limit_height < _loaded.height){
_loaded = Doxa::ImageResize::resize_to_height(_loaded, args.limit_height, interpolation);
}
else if (args.limit_width_given && args.limit_width < _loaded.width){
_loaded = Doxa::ImageResize::resize_to_width(_loaded, args.limit_height, interpolation);
}
return _loaded;
}();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment