Skip to content

Commit

Permalink
image4: complete command-line option parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
hollasch committed Nov 2, 2024
1 parent 2f0b87c commit 2ba14fe
Showing 1 changed file with 143 additions and 31 deletions.
174 changes: 143 additions & 31 deletions ray4/src/image4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
using namespace std;


//==================================================================================================
//__________________________________________________________________________________________________
// Information Text Definitions

static auto version = L"image4 0.0.0 | 2024-10-31 | https://github.com/hollasch/ray4/tree/master/image4";
Expand Down Expand Up @@ -82,28 +82,30 @@ options.
If a horizontalCount is specified, then each row will have the specified number of
thumbnails, sized to fit, with as tall a result as needed to display all slices.
-c, --crop <minX>,<minY>-<maxX>,<maxY>
-c, --crop <xMin>,<yMin>-<xMax>,<yMax>
Output images may be optionally cropped to the specified region. If specified, all images will
be similarly cropped.
)";

//__________________________________________________________________________________________________

struct Parameters {
bool printHelp {false};
wstring imageCubeFilename;
bool printFileInfo {false};
wstring outputFilePattern;
int sliceStart{0};
int sliceEnd{-1};
int sliceStep{1};
bool showTiled{false};
int tiledPixelWidth{0};
int tiledHorizontalCount{0};
int cropXMin{0};
int cropXMax{-1};
int cropYMin{0};
int cropYMax{-1};
bool printHelp{false}; // Print help and version information.
wstring imageCubeFilename; // Input image cube file name
bool printFileInfo{false}; // Print information about the image cube file.
wstring outputFilePattern; // Output image file name pattern
int sliceStart{0}; // First slice to output
int sliceEnd{-1}; // Last output slice. -1 indicates last slice
int sliceStep{1}; // Step size between slices
bool showTiled{false}; // Generate a tiled contact sheet of thumbnails.
int tiledPixelWidth{0}; // Width in pixels of tiled contact sheet
int tiledHorizontalCount{0}; // Number of thumbnails per row in tiled contact sheet
int cropXMin{0}; // Minimum X coordinate for cropped output images
int cropXMax{-1}; // Maximum X coordinate for cropped output images
int cropYMin{0}; // Minimum Y coordinate for cropped output images
int cropYMax{-1}; // Maximum Y coordinate for cropped output images
};

//__________________________________________________________________________________________________

enum class OptionType {
Expand Down Expand Up @@ -137,9 +139,11 @@ static vector<OptionInfo> optionInfo = {
{OptionType::Tiled, L't', L"tiled", true},
{OptionType::Crop, L'c', L"crop", true},
};

//__________________________________________________________________________________________________

const OptionInfo& getOptionInfo(wchar_t *arg) {
// Given a command-line option, return the corresponding OptionInfo structure.

if (arg[0] == L'/' && arg[1] == L'?')
return optionInfo[1];
Expand All @@ -159,46 +163,142 @@ const OptionInfo& getOptionInfo(wchar_t *arg) {

return optionInfo[0];
}

//__________________________________________________________________________________________________

std::pair<wchar_t*, int> readInteger (wchar_t* str) {
// Reads the integer from the string. Returns a pair containing the pointer to the remainder of
// the string, and the integer value.

auto *ptr = str;
bool negate = *ptr == L'-';
if (negate) ++ptr;

int value = 0;
for (; isdigit(*ptr); ++ptr)
value = (10 * value) + (*ptr - L'0');

return { ptr, negate ? -value : value };
}

//__________________________________________________________________________________________________

bool parseOptionValueSlice (Parameters &params, wchar_t* value) {
// Parse the slice option string. Format is '<start>[-<end>][x<stepSize>]'.
// Parse the --slice option string. Format is '<start>[-<end>][x<stepSize>]'.

const auto optionValue = value;

if (!isdigit(*value)) {
wcerr << "image4: Invalid slice start (" << optionValue << ").\n";
return false;
}

std::tie(value, params.sliceStart) = readInteger(value);

if (atoi
if (*value == '-') {
++value;
if (!isdigit(*value)) {
wcerr << "image4: Invalid slice end (" << optionValue << ").\n";
return false;
}
std::tie(value, params.sliceEnd) = readInteger(value);
}

if (*value == 'x') {
++value;
if (!isdigit(*value)) {
wcerr << "image4: Invalid slice step (" << optionValue << ").\n";
return false;
}
std::tie(value, params.sliceStep) = readInteger(value);
}

if (*value) {
wcerr << "image4: Invalid slice option value (" << optionValue << ").\n";
return false;
}

params.sliceStart = 1;
params.sliceEnd = -1;
params.sliceStep = -1;
return true;
}

//__________________________________________________________________________________________________

bool parseOptionValueTiled (Parameters &params, wchar_t* value) {
params.showTiled = true;
params.tiledPixelWidth = -1;
params.tiledHorizontalCount = -1;
// Parse the --tiled option string. Format is '<pixelWidth>[x<horizontalCount]'.

const auto optionValue = value;

if (!isdigit(*value)) {
wcerr << "image4: Invalid tiled pixel width (" << optionValue << ").\n";
return false;
}

std::tie(value, params.tiledPixelWidth) = readInteger(value);

if (*value == 'x') {
++value;
if (!isdigit(*value)) {
wcerr << "image4: Invalid tiled horizontal count (" << optionValue << ").\n";
return false;
}
std::tie(value, params.tiledHorizontalCount) = readInteger(value);
}

if (*value) {
wcerr << "image4: Invalid tiled option value (" << optionValue << ").\n";
return false;
}

return true;
}

//__________________________________________________________________________________________________

bool parseOptionValueCrop (Parameters &params, wchar_t* value) {
params.cropXMin = 0;
params.cropYMin = 0;
params.cropYMax = -1;
params.cropYMin = -1;
// Parse the --crop option string. Format is '<xMin>,<yMin>-<xMax>,<yMax>'.

const auto optionValue = value;

if (!isdigit(*value)) {
wcerr << "image4: Invalid crop X minimum (" << optionValue << ").\n";
return false;
}
std::tie(value, params.cropXMin) = readInteger(value);

if (*value != ',' || !isdigit(*++value)) {
wcerr << "image4: Invalid crop option value (" << optionValue << ").\n";
return false;
}
std::tie(value, params.cropYMin) = readInteger(value);

if (*value != '-' || !isdigit(*++value)) {
wcerr << "image4: Invalid crop option value (" << optionValue << ").\n";
return false;
}
std::tie(value, params.cropXMax) = readInteger(value);

if (*value != ',' || !isdigit(*++value)) {
wcerr << "image4: Invalid crop option value (" << optionValue << ").\n";
return false;
}
std::tie(value, params.cropYMax) = readInteger(value);

if (*value) {
wcerr << "image4: Invalid tiled option value (" << optionValue << ").\n";
return false;
}

return true;
}

//__________________________________________________________________________________________________

bool processParameters (Parameters &params, int argc, wchar_t *argv[]) {
// Process the command-line options and load results into the given Parameters object. Returns
// true on success, false on error.

wcout << "\nArguments:\n";
for (auto argi = 1; argi < argc; ++argi) {
auto *arg = argv[argi];
wcout << argi << ": " << arg << '\n';

auto optionInfo = getOptionInfo(arg);
wchar_t *optionValue = nullptr;

Expand Down Expand Up @@ -261,6 +361,7 @@ bool processParameters (Parameters &params, int argc, wchar_t *argv[]) {

return true;
}

//__________________________________________________________________________________________________

int wmain(int argc, wchar_t *argv[]) {
Expand All @@ -269,6 +370,17 @@ int wmain(int argc, wchar_t *argv[]) {
if (!processParameters(params, argc, argv))
return 1;

if (params.printHelp) {
wcout << usage;
wcout << version;
return 0;
}

if (params.imageCubeFilename.empty()) {
wcerr << "image4: Missing input image file name.\n";
return 1;
}

wcout << "\nCommand-line parameters:\n";
wcout << " printHelp: " << (params.printHelp ? "true\n" : "false\n");
wcout << " imageCubeFilename: '" << params.imageCubeFilename << "'\n";
Expand Down

0 comments on commit 2ba14fe

Please sign in to comment.