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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
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;
#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;
}
}
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_;
/// 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.
* \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_;