]> git.seodisparate.com - EN605.617.81.FA21_StephenSeo_DitheringProject/commitdiff
Add arg parsing
authorStephen Seo <seo.disparate@gmail.com>
Wed, 1 Dec 2021 08:31:51 +0000 (17:31 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 1 Dec 2021 08:31:51 +0000 (17:31 +0900)
CMakeLists.txt
src/arg_parse.cc [new file with mode: 0644]
src/arg_parse.h [new file with mode: 0644]
src/image.cc
src/main.cc
src/video.cc
src/video.h

index 368bc1a7ee3bc68472188027055a194eaad748c5..6939390c6686489964b44ae272a15c328c26645a 100644 (file)
@@ -3,6 +3,7 @@ project(EN605.617.81.FA21_StephenSeo_DitheringProject)
 
 set(Project_SOURCES
   ${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/video.cc
   ${CMAKE_CURRENT_SOURCE_DIR}/src/opencl_handle.cc
diff --git a/src/arg_parse.cc b/src/arg_parse.cc
new file mode 100644 (file)
index 0000000..b61c9fa
--- /dev/null
@@ -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;
+}
diff --git a/src/arg_parse.h b/src/arg_parse.h
new file mode 100644 (file)
index 0000000..5f62494
--- /dev/null
@@ -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
index 90712d2dad1751464f8d42fbe387bc1ee577a1f4..284abf0efa156bdb0d06ff81131df8e2083d18ea 100644 (file)
@@ -64,7 +64,11 @@ Image::Image(const std::string &filename)
       is_dithered_grayscale_(false),
       is_dithered_color_(false),
       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
     std::cout << "INFO: PNG filename extension detected, decoding..."
               << std::endl;
index 93093770acf11f9542e82c866ac98ea90d3db40f..e6c172082bdd2d5e1257c326c9f7d4f7213ca177 100644 (file)
@@ -1,19 +1,72 @@
 #include <iostream>
 
+#include "arg_parse.h"
 #include "image.h"
 #include "video.h"
 
 int main(int argc, char **argv) {
-  Image blue_noise("bluenoise.png");
-  if (!blue_noise.IsValid()) {
-    std::cout << "ERROR: Invalid bluenoise.png" << std::endl;
-    return 1;
+  Args args{};
+  if (args.ParseArgs(argc, argv)) {
+    return 0;
   }
-  Video video("input.mp4");
-  if (!video.DitherVideo("output.mp4", &blue_noise, false)) {
-    std::cout << "ERROR: Failed to dither video" << std::endl;
+
+  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;
   }
 
+  if (args.do_dither_image_) {
+    Image input_image(args.input_filename);
+    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;
 }
index bcf8795d3bb5d7ea417630b9fd254da676cda360..a06722e3f8fbf50c1f39e86395b3b4132d30773b 100644 (file)
@@ -25,12 +25,13 @@ Video::~Video() {
 }
 
 bool Video::DitherVideo(const char *output_filename, Image *blue_noise,
-                        bool grayscale) {
-  return DitherVideo(std::string(output_filename), blue_noise, grayscale);
+                        bool grayscale, bool overwrite) {
+  return DitherVideo(std::string(output_filename), blue_noise, grayscale,
+                     overwrite);
 }
 
 bool Video::DitherVideo(const std::string &output_filename, Image *blue_noise,
-                        bool grayscale) {
+                        bool grayscale, bool overwrite) {
   // Get AVFormatContext for input file
   AVFormatContext *avf_context = nullptr;
   std::string url = std::string("file:") + input_filename_;
index e42e36e1fed54907ea674094a68c2fe9ae9c64f3..7d9c675fff0bdd3e2360099b75da8c3a0f443d2a 100644 (file)
@@ -27,7 +27,7 @@ class Video {
 
   /// Same as DitherVideo(const std::string&, Image*, bool)
   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.
@@ -39,7 +39,7 @@ class Video {
    * \return True on success.
    */
   bool DitherVideo(const std::string &output_filename, Image *blue_noise,
-                   bool grayscale = false);
+                   bool grayscale = false, bool overwrite = false);
 
  private:
   Image image_;