Add arg parsing

This commit is contained in:
Stephen Seo 2021-12-01 17:31:51 +09:00
parent af7b28f794
commit 07d931126f
7 changed files with 163 additions and 13 deletions

View file

@ -3,6 +3,7 @@ project(EN605.617.81.FA21_StephenSeo_DitheringProject)
set(Project_SOURCES set(Project_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/arg_parse.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/image.cc ${CMAKE_CURRENT_SOURCE_DIR}/src/image.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/video.cc ${CMAKE_CURRENT_SOURCE_DIR}/src/video.cc
${CMAKE_CURRENT_SOURCE_DIR}/src/opencl_handle.cc ${CMAKE_CURRENT_SOURCE_DIR}/src/opencl_handle.cc

69
src/arg_parse.cc Normal file
View file

@ -0,0 +1,69 @@
#include "arg_parse.h"
#include <cstring>
#include <iostream>
Args::Args()
: do_dither_image_(true),
do_dither_grayscaled_(false),
do_overwrite_(false),
input_filename(),
output_filename() {}
void Args::PrintUsage() {
std::cout
<< "Usage: [-h | --help] [-i <filename> | --input <filename>] [-o "
"<filename> | --output <filename>] [-b <filename> | --blue "
"<filename>] [-g | --gray] [--image] [--video] [--overwrite]\n"
" -h | --help\t\t\t\tPrint this usage text\n"
" -i <filename> | --input <filename>\tSet input filename\n"
" -o <filename> | --output <filename>\tSet output filename\n"
" -b <filename> | --blue <filename>\tSet input blue_noise filename\n"
" -g | --gray\t\t\t\tDither output in grayscale\n"
" --image\t\t\t\tDither a single image\n"
" --video\t\t\t\tDither frames in a video\n"
" --overwrite\t\t\t\tAllow overwriting existing files\n"
<< std::endl;
}
bool Args::ParseArgs(int argc, char **argv) {
--argc;
++argv;
while (argc > 0) {
if (std::strcmp(argv[0], "-h") == 0 ||
std::strcmp(argv[0], "--help") == 0) {
PrintUsage();
return true;
} else if (argc > 1 && (std::strcmp(argv[0], "-i") == 0 ||
std::strcmp(argv[0], "--input") == 0)) {
input_filename = std::string(argv[1]);
--argc;
++argv;
} else if (argc > 1 && (std::strcmp(argv[0], "-o") == 0 ||
std::strcmp(argv[0], "--output") == 0)) {
output_filename = std::string(argv[1]);
--argc;
++argv;
} else if (argc > 1 && (std::strcmp(argv[0], "-b") == 0 ||
std::strcmp(argv[0], "--blue") == 0)) {
blue_noise_filename = std::string(argv[1]);
--argc;
++argv;
} else if (std::strcmp(argv[0], "-g") == 0 ||
std::strcmp(argv[0], "--gray") == 0) {
do_dither_grayscaled_ = true;
} else if (std::strcmp(argv[0], "--image") == 0) {
do_dither_image_ = true;
} else if (std::strcmp(argv[0], "--video") == 0) {
do_dither_image_ = false;
} else if (std::strcmp(argv[0], "--overwrite") == 0) {
do_overwrite_ = true;
} else {
std::cout << "WARNING: Ignoring invalid input \"" << argv[0] << '"'
<< std::endl;
}
--argc;
++argv;
}
return false;
}

22
src/arg_parse.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef IGPUP_DITHERING_PROJECT_ARG_PARSE_
#define IGPUP_DITHERING_PROJECT_ARG_PARSE_
#include <string>
struct Args {
Args();
static void PrintUsage();
/// Returns true if help was printed
bool ParseArgs(int argc, char **argv);
bool do_dither_image_;
bool do_dither_grayscaled_;
bool do_overwrite_;
std::string input_filename;
std::string output_filename;
std::string blue_noise_filename;
};
#endif

View file

@ -64,7 +64,11 @@ Image::Image(const std::string &filename)
is_dithered_grayscale_(false), is_dithered_grayscale_(false),
is_dithered_color_(false), is_dithered_color_(false),
is_preserving_blue_noise_offsets_(true) { is_preserving_blue_noise_offsets_(true) {
if (filename.compare(filename.size() - 4, filename.size(), ".png") == 0) { if (filename.empty()) {
std::cout << "ERROR: Image got empty filename string" << std::endl;
return;
} else if (filename.compare(filename.size() - 4, filename.size(), ".png") ==
0) {
// filename expected to be .png // filename expected to be .png
std::cout << "INFO: PNG filename extension detected, decoding..." std::cout << "INFO: PNG filename extension detected, decoding..."
<< std::endl; << std::endl;

View file

@ -1,18 +1,71 @@
#include <iostream> #include <iostream>
#include "arg_parse.h"
#include "image.h" #include "image.h"
#include "video.h" #include "video.h"
int main(int argc, char **argv) { int main(int argc, char **argv) {
Image blue_noise("bluenoise.png"); Args args{};
if (!blue_noise.IsValid()) { if (args.ParseArgs(argc, argv)) {
std::cout << "ERROR: Invalid bluenoise.png" << std::endl; return 0;
}
Image blue_noise(args.blue_noise_filename);
if (!blue_noise.IsValid() || !blue_noise.IsGrayscale()) {
std::cout << "ERROR: Invalid blue noise file \"" << args.blue_noise_filename
<< '"' << std::endl;
Args::PrintUsage();
return 1; return 1;
} }
Video video("input.mp4");
if (!video.DitherVideo("output.mp4", &blue_noise, false)) { if (args.do_dither_image_) {
std::cout << "ERROR: Failed to dither video" << std::endl; Image input_image(args.input_filename);
return 1; if (!input_image.IsValid()) {
std::cout << "ERROR: Invalid input image file \"" << args.input_filename
<< '"' << std::endl;
Args::PrintUsage();
return 2;
}
if (args.do_dither_grayscaled_) {
auto output_image =
input_image.ToGrayscaleDitheredWithBlueNoise(&blue_noise);
if (!output_image) {
std::cout << "ERROR: Failed to dither input image \""
<< args.input_filename << '"' << std::endl;
Args::PrintUsage();
return 3;
}
if (!output_image->SaveAsPNG(args.output_filename, args.do_overwrite_)) {
std::cout << "ERROR: Failed to saved dithered image from input \""
<< args.input_filename << '"' << std::endl;
Args::PrintUsage();
return 4;
}
} else {
auto output_image = input_image.ToColorDitheredWithBlueNoise(&blue_noise);
if (!output_image) {
std::cout << "ERROR: Failed to dither input image \""
<< args.input_filename << '"' << std::endl;
Args::PrintUsage();
return 5;
}
if (!output_image->SaveAsPNG(args.output_filename, args.do_overwrite_)) {
std::cout << "ERROR: Failed to saved dithered image from input \""
<< args.input_filename << '"' << std::endl;
Args::PrintUsage();
return 6;
}
}
} else {
Video video(args.input_filename);
if (!video.DitherVideo(args.output_filename, &blue_noise,
args.do_dither_grayscaled_, args.do_overwrite_)) {
std::cout << "ERROR: Failed to dither frames from input video \""
<< args.input_filename << '"' << std::endl;
Args::PrintUsage();
return 7;
}
} }
return 0; return 0;

View file

@ -25,12 +25,13 @@ Video::~Video() {
} }
bool Video::DitherVideo(const char *output_filename, Image *blue_noise, bool Video::DitherVideo(const char *output_filename, Image *blue_noise,
bool grayscale) { bool grayscale, bool overwrite) {
return DitherVideo(std::string(output_filename), blue_noise, grayscale); return DitherVideo(std::string(output_filename), blue_noise, grayscale,
overwrite);
} }
bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise, bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
bool grayscale) { bool grayscale, bool overwrite) {
// Get AVFormatContext for input file // Get AVFormatContext for input file
AVFormatContext *avf_context = nullptr; AVFormatContext *avf_context = nullptr;
std::string url = std::string("file:") + input_filename_; std::string url = std::string("file:") + input_filename_;

View file

@ -27,7 +27,7 @@ class Video {
/// Same as DitherVideo(const std::string&, Image*, bool) /// Same as DitherVideo(const std::string&, Image*, bool)
bool DitherVideo(const char *output_filename, Image *blue_noise, bool DitherVideo(const char *output_filename, Image *blue_noise,
bool grayscale = false); bool grayscale = false, bool overwrite = false);
/*! /*!
* \brief Dithers the frames in the input video. * \brief Dithers the frames in the input video.
@ -39,7 +39,7 @@ class Video {
* \return True on success. * \return True on success.
*/ */
bool DitherVideo(const std::string &output_filename, Image *blue_noise, bool DitherVideo(const std::string &output_filename, Image *blue_noise,
bool grayscale = false); bool grayscale = false, bool overwrite = false);
private: private:
Image image_; Image image_;