2022-03-15 10:52:23 -06:00
|
|
|
/*
|
|
|
|
|
|
|
|
uirc: an unnecessary image ratio calculator
|
|
|
|
Created by Bryson Steck (@brysonsteck on GitHub)
|
|
|
|
Free and Open Source Software under the BSD 2-Clause License
|
|
|
|
|
|
|
|
BSD 2-Clause License
|
|
|
|
|
|
|
|
Copyright (c) 2022, Bryson Steck
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
|
|
|
list of conditions and the following disclaimer.
|
|
|
|
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2022-03-22 14:22:32 -06:00
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
|
|
|
2022-03-07 16:12:40 -07:00
|
|
|
#include <stdio.h>
|
2022-03-14 14:31:03 -06:00
|
|
|
#include <stb/stb_image.h>
|
2022-03-22 14:22:32 -06:00
|
|
|
#include <curl/curl.h>
|
2022-03-23 20:45:20 -06:00
|
|
|
#include <curl/easy.h>
|
2022-03-25 14:00:43 -06:00
|
|
|
#include <unistd.h>
|
2022-06-20 23:25:44 -06:00
|
|
|
#include <stdbool.h>
|
2022-03-07 16:12:40 -07:00
|
|
|
|
|
|
|
const char *VERSION = "0.1.0";
|
2022-06-21 22:22:01 -06:00
|
|
|
bool singular = false;
|
2022-03-25 14:00:43 -06:00
|
|
|
int rFlag = 1;
|
2022-03-07 16:12:40 -07:00
|
|
|
|
2022-03-23 21:01:14 -06:00
|
|
|
int getBcf(int width, int height) {
|
|
|
|
int *widthFactors, *heightFactors;
|
|
|
|
int bcf;
|
|
|
|
for (int i = 1; i <= width; i++) {
|
|
|
|
for (int j = 1; j <= height; j++) {
|
|
|
|
if (width % i == 0) {
|
|
|
|
if (height % j == 0 && i == j) {
|
|
|
|
bcf = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bcf;
|
|
|
|
}
|
|
|
|
|
2022-06-20 23:25:44 -06:00
|
|
|
bool compare_float(float a, float b) {
|
2022-06-21 22:22:01 -06:00
|
|
|
return fabs(a-b) < 0.001;
|
2022-06-20 23:25:44 -06:00
|
|
|
}
|
|
|
|
|
2022-03-23 21:01:14 -06:00
|
|
|
int readFile(char *file, int rFlag, int req, char* url) {
|
2022-06-21 22:22:01 -06:00
|
|
|
char *displayfile;
|
2022-03-23 21:01:14 -06:00
|
|
|
int width, height, channels, factor;
|
|
|
|
unsigned char *img = stbi_load(file, &width, &height, &channels, 0);
|
2022-06-21 22:22:01 -06:00
|
|
|
|
2022-03-23 21:01:14 -06:00
|
|
|
if (img == NULL) {
|
|
|
|
if (req == 0) {
|
2022-03-25 14:04:36 -06:00
|
|
|
printf("FAIL\nuirc: request failed (%s), trying local fs instead\n", url);
|
2022-03-23 21:01:14 -06:00
|
|
|
return 4;
|
2022-03-25 14:00:43 -06:00
|
|
|
} else if (access(file, F_OK) != 0) {
|
|
|
|
printf("uirc: %s: No such file or directory\n", file);
|
|
|
|
exit(6);
|
2022-03-23 21:01:14 -06:00
|
|
|
} else {
|
2022-03-25 14:00:43 -06:00
|
|
|
printf("uirc: could not open file %s: %s\n", file, stbi_failure_reason());
|
2022-03-24 11:15:36 -06:00
|
|
|
exit(3);
|
2022-03-23 21:01:14 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-25 14:04:36 -06:00
|
|
|
if (req == 0)
|
|
|
|
printf("ok\n");
|
|
|
|
|
2022-03-23 21:01:14 -06:00
|
|
|
factor = getBcf(width, height);
|
|
|
|
stbi_image_free(img);
|
|
|
|
double wuneven = ((float) height) / ((float) width);
|
|
|
|
double huneven = ((float) width) / ((float) height);
|
|
|
|
|
|
|
|
if (req == 0) {
|
2022-03-25 14:00:43 -06:00
|
|
|
char *token, *next = "";
|
|
|
|
|
|
|
|
token = strtok(url, "/");
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (next == NULL) {
|
|
|
|
file = token;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
token = next;
|
|
|
|
next = strtok(NULL, "/");
|
|
|
|
}
|
2022-03-23 21:01:14 -06:00
|
|
|
}
|
|
|
|
|
2022-06-21 22:22:01 -06:00
|
|
|
if (singular)
|
|
|
|
displayfile = "";
|
|
|
|
else {
|
|
|
|
displayfile = (char*) malloc(CHAR_MAX);
|
|
|
|
strcpy(displayfile, file);
|
|
|
|
strcat(displayfile, " > ");
|
|
|
|
}
|
2022-06-20 23:25:44 -06:00
|
|
|
|
2022-06-21 22:22:01 -06:00
|
|
|
// see if uneven values equal normal aspect ratios
|
|
|
|
// aspect ratios obtained from https://en.wikipedia.org/wiki/Aspect_ratio_(image)
|
|
|
|
bool bestFit = false;
|
|
|
|
|
|
|
|
if (width < height) {
|
|
|
|
if (compare_float(wuneven, 1.77777777)) {
|
|
|
|
// 9:16
|
|
|
|
printf("%s9:16", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 1.33333333)) {
|
|
|
|
// 3:4
|
|
|
|
printf("%s3:4", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 0.46153846)) {
|
|
|
|
// 6:13
|
|
|
|
printf("%s6:13", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 1.25)) {
|
|
|
|
// 4:5
|
|
|
|
printf("%s4:5", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 1.5)) {
|
|
|
|
// 2:3
|
|
|
|
printf("%s2:3", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 1.6)) {
|
|
|
|
// 10:16
|
|
|
|
printf("%s10:16", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 2.37037037)) {
|
|
|
|
// 27:64
|
|
|
|
printf("%s27:64", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 3.55555555)) {
|
|
|
|
// 9:32
|
|
|
|
printf("%s9:32", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 1.66666666)) {
|
|
|
|
// 3:5
|
|
|
|
printf("%s3:5", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 1.6180)) {
|
|
|
|
// golden ratio
|
|
|
|
printf("%s1:1.6180 (GOLDEN RATIO!!!!)", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 1.85)) {
|
|
|
|
// 1:1.85
|
|
|
|
printf("%s1:1.85", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 2.33333333)) {
|
|
|
|
// 9:21
|
|
|
|
printf("%s9:21", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(wuneven, 1.55555555)) {
|
|
|
|
// 9:14
|
|
|
|
printf("%s9:14", displayfile);
|
|
|
|
bestFit = true;
|
2022-03-23 21:01:14 -06:00
|
|
|
}
|
|
|
|
} else {
|
2022-06-21 22:22:01 -06:00
|
|
|
if (compare_float(huneven, 1.77777777)) {
|
|
|
|
// 16:9
|
|
|
|
printf("%s16:9", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 1.33333333)) {
|
|
|
|
// 4:3
|
|
|
|
printf("%s4:3", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 0.46153846)) {
|
|
|
|
// 13:6
|
|
|
|
printf("%s13:6", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 1.25)) {
|
|
|
|
// 5:4
|
|
|
|
printf("%s5:4", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 1.5)) {
|
|
|
|
// 3:2
|
|
|
|
printf("%s3:2", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 1.6)) {
|
|
|
|
// 16:10
|
|
|
|
printf("%s16:10", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 2.37037037)) {
|
|
|
|
// 64:27
|
|
|
|
printf("%s64:27", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 3.55555555)) {
|
|
|
|
// 32:9
|
|
|
|
printf("%s32:9", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 1.66666666)) {
|
|
|
|
// 5:3
|
|
|
|
printf("%s5:3", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 1.6180)) {
|
|
|
|
// golden ratio
|
|
|
|
printf("%s1.6180:1 (GOLDEN RATIO!!!!)", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 1.85)) {
|
|
|
|
// 1.85:1
|
|
|
|
printf("%s1.85:1", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 2.33333333)) {
|
|
|
|
// 21:9
|
|
|
|
printf("%s21:9", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
} else if (compare_float(huneven, 1.55555555)) {
|
|
|
|
// 14:9
|
|
|
|
printf("%s14:9", displayfile);
|
|
|
|
bestFit = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bestFit) {
|
|
|
|
if (factor == 1) {
|
|
|
|
if (width < height) {
|
|
|
|
printf("%s1:%.2f (uneven)", displayfile, wuneven);
|
|
|
|
} else {
|
|
|
|
printf("%s%.2f:1 (uneven)", displayfile, huneven);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
printf("%s%d:%d", displayfile, width / factor, height / factor);
|
|
|
|
}
|
2022-03-23 21:01:14 -06:00
|
|
|
}
|
2022-06-21 22:22:01 -06:00
|
|
|
|
2022-03-24 11:15:36 -06:00
|
|
|
if (rFlag == 0)
|
|
|
|
printf(" [%dx%d]\n", width, height);
|
|
|
|
else
|
|
|
|
printf("\n");
|
2022-06-21 22:22:01 -06:00
|
|
|
|
2022-03-23 21:01:14 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// thanks :) https://stackoverflow.com/questions/19404616/c-program-for-downloading-files-with-curl
|
|
|
|
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
|
|
|
size_t written = fwrite(ptr, size, nmemb, stream);
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
|
|
|
|
int download(char *url) {
|
|
|
|
CURL *curl;
|
|
|
|
FILE *fp;
|
|
|
|
CURLcode res;
|
2022-03-25 14:00:43 -06:00
|
|
|
char outfilename[15] = "/tmp/uirc.tmp";
|
2022-03-23 21:01:14 -06:00
|
|
|
curl = curl_easy_init();
|
2022-06-20 23:25:44 -06:00
|
|
|
long returnCode = 0;
|
2022-03-25 14:00:43 -06:00
|
|
|
|
2022-03-23 21:01:14 -06:00
|
|
|
if (curl) {
|
|
|
|
fp = fopen(outfilename,"wb");
|
|
|
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
|
|
|
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
|
|
|
|
res = curl_easy_perform(curl);
|
2022-06-20 23:25:44 -06:00
|
|
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, returnCode);
|
2022-03-23 21:01:14 -06:00
|
|
|
curl_easy_cleanup(curl);
|
|
|
|
fclose(fp);
|
|
|
|
}
|
2022-03-25 14:04:36 -06:00
|
|
|
|
2022-06-21 22:22:01 -06:00
|
|
|
//printf("%ld\n", returnCode);
|
2022-03-23 21:01:14 -06:00
|
|
|
return 0;
|
|
|
|
}
|
2022-03-24 11:15:36 -06:00
|
|
|
// end of stack overflow snippet
|
|
|
|
|
2022-06-21 22:22:01 -06:00
|
|
|
int handleArg(char *arg, int argc) {
|
2022-06-20 23:25:44 -06:00
|
|
|
int complete;
|
|
|
|
char flag, first, firstTwo[3], firstFour[5];
|
2022-03-14 14:31:03 -06:00
|
|
|
const char *help;
|
2022-03-07 16:12:40 -07:00
|
|
|
|
2022-04-21 14:14:18 -06:00
|
|
|
help = "USAGE: uirc [OPTIONS] IMAGE1 [IMAGE2] [...]\n\n"
|
2022-03-07 16:25:52 -07:00
|
|
|
|
2022-03-15 10:52:23 -06:00
|
|
|
"OPTIONS:\n"
|
2022-04-21 14:14:18 -06:00
|
|
|
"informational:\n"
|
|
|
|
" -h, --help \t: Display this message\n"
|
|
|
|
" -l, --license\t: Display the license disclaimer for uirc (BSD 2-Clause)\n"
|
|
|
|
" -v, --version\t: Display the version of uirc\n\n"
|
2022-03-07 16:25:52 -07:00
|
|
|
|
2022-04-21 14:14:18 -06:00
|
|
|
"functional:\n"
|
|
|
|
" -r, --res \t: Display the resolution of the image (in addition to the ratio)\n\n"
|
2022-03-07 16:25:52 -07:00
|
|
|
|
2022-04-21 14:14:18 -06:00
|
|
|
"HELP:\n"
|
|
|
|
"For more information on how to use uirc, open the man page uirc(1).\n";
|
2022-03-07 16:12:40 -07:00
|
|
|
|
|
|
|
first = arg[0];
|
|
|
|
|
2022-03-23 20:45:20 -06:00
|
|
|
firstFour[0] = arg[0];
|
|
|
|
firstFour[1] = arg[1];
|
|
|
|
firstFour[2] = arg[2];
|
|
|
|
firstFour[3] = arg[3];
|
|
|
|
firstFour[4] = '\0';
|
|
|
|
|
2022-03-07 16:12:40 -07:00
|
|
|
firstTwo[0] = arg[0];
|
|
|
|
firstTwo[1] = arg[1];
|
|
|
|
firstTwo[2] = '\0';
|
2022-03-24 11:15:36 -06:00
|
|
|
|
|
|
|
if (strcmp("--", firstTwo) == 0 || '-' == first) {
|
|
|
|
if (strcmp("--help", arg) == 0 || strcmp("-h", arg) == 0) {
|
|
|
|
printf("an unneccessary image ratio calculator (uirc) v%s\n\n", VERSION);
|
|
|
|
printf("Copyright 2022 Bryson Steck\nFree and Open Source under the BSD 2-Clause License\n\n");
|
|
|
|
printf("%s\n", help);
|
|
|
|
exit(1);
|
|
|
|
} else if (strcmp("--license", arg) == 0 || strcmp("-l", arg) == 0) {
|
|
|
|
printf("uirc is Free and Open Source Software under the BSD 2-Clause License.\n");
|
|
|
|
printf("Please read the license regarding copying and distributing uirc.\n");
|
|
|
|
printf("https://github.com/brysonsteck/uirc/blob/master/LICENSE\n");
|
|
|
|
exit(1);
|
|
|
|
} else if (strcmp("--res", arg) == 0 || strcmp("-r", arg) == 0) {
|
2022-06-21 22:22:01 -06:00
|
|
|
if (rFlag == 0) {
|
|
|
|
printf("uirc: -r / --res flag is used way too many times\n");
|
|
|
|
exit(9);
|
|
|
|
}
|
2022-03-24 11:15:36 -06:00
|
|
|
rFlag = 0;
|
2022-06-21 22:22:01 -06:00
|
|
|
if (argc == 3)
|
|
|
|
singular = true;
|
2022-03-24 11:15:36 -06:00
|
|
|
return 0;
|
2022-04-21 14:14:18 -06:00
|
|
|
} else if (strcmp("--version", arg) == 0 || strcmp("-v", arg) == 0) {
|
|
|
|
printf("uirc v%s", VERSION);
|
|
|
|
exit(1);
|
2022-03-24 11:15:36 -06:00
|
|
|
} else {
|
|
|
|
printf("uirc: invalid argument \"%s\"\nType \"uirc --help\" for help with arguments.\n", arg);
|
|
|
|
exit(5);
|
2022-03-07 16:12:40 -07:00
|
|
|
}
|
|
|
|
}
|
2022-03-25 14:00:43 -06:00
|
|
|
|
2022-06-21 22:22:01 -06:00
|
|
|
if (argc == 2)
|
|
|
|
singular = true;
|
|
|
|
|
2022-03-24 11:15:36 -06:00
|
|
|
if (strcmp("http", firstFour) == 0) {
|
2022-03-25 14:00:43 -06:00
|
|
|
printf("downloading \"%s\"...", arg);
|
|
|
|
fflush(stdout);
|
2022-03-23 20:45:20 -06:00
|
|
|
download(arg);
|
2022-03-24 11:15:36 -06:00
|
|
|
complete = readFile("/tmp/uirc.tmp", rFlag, 0, arg);
|
|
|
|
if (complete != 0)
|
|
|
|
readFile(arg, rFlag, 1, "");
|
2022-03-25 14:00:43 -06:00
|
|
|
else
|
|
|
|
remove("/tmp/uirc.tmp");
|
2022-03-23 20:45:20 -06:00
|
|
|
} else {
|
|
|
|
// if no more flags, run ratio calculations
|
2022-03-23 21:01:14 -06:00
|
|
|
return readFile(arg, rFlag, 1, "");
|
2022-03-23 20:45:20 -06:00
|
|
|
}
|
2022-06-21 22:22:01 -06:00
|
|
|
|
2022-04-21 14:14:18 -06:00
|
|
|
return 0;
|
2022-03-07 16:12:40 -07:00
|
|
|
}
|
|
|
|
|
2022-03-22 14:22:32 -06:00
|
|
|
int main(int argc, char *argv[]) {
|
2022-03-24 11:15:36 -06:00
|
|
|
char *i, *a;
|
2022-06-20 23:25:44 -06:00
|
|
|
int runs, code, arg_code;
|
2022-03-07 16:12:40 -07:00
|
|
|
|
|
|
|
if (argc <= 1) {
|
|
|
|
printf("uirc: at least one argument is required\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-03-15 10:52:23 -06:00
|
|
|
for (int i = 1; i < argc; i++) {
|
2022-03-24 11:15:36 -06:00
|
|
|
a = argv[i];
|
2022-06-21 22:22:01 -06:00
|
|
|
arg_code = handleArg(a, argc);
|
2022-06-20 23:25:44 -06:00
|
|
|
if (arg_code > code)
|
|
|
|
code = arg_code;
|
2022-03-24 11:15:36 -06:00
|
|
|
runs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (runs < 2 && rFlag == 0) {
|
|
|
|
printf("uirc: at least one file/url is required\n");
|
|
|
|
return 1;
|
2022-03-15 10:52:23 -06:00
|
|
|
}
|
2022-03-23 20:45:20 -06:00
|
|
|
|
|
|
|
return 0;
|
2022-03-07 16:12:40 -07:00
|
|
|
}
|
|
|
|
|