Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Autocrop by Munashe
- // 4-6-2023
- // Drag and drop scanned photoes onto the exe to automatically crop them.
- // Only supports jpeg
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #ifdef __linux__
- #include <sys/types.h>
- #include <dirent.h>
- #elif _WIN32
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #define mkdir(dir, mode) _mkdir(dir)
- #else
- // unsupported
- #endif
- #define STB_IMAGE_IMPLEMENTATION
- #include "stb_image.h"
- #define STB_IMAGE_WRITE_IMPLEMENTATION
- #include "stb_image_write.h"
- #define THRESHOLD 600
- #define SCRATCH_CAP 1024
- char scratch[SCRATCH_CAP] = {0};
- const char out_folder[] = "output";
- typedef struct Pixel { unsigned char r; unsigned char g; unsigned char b; } Pixel;
- void top_to_bottom(unsigned char *bytes, int width, int height, int *top, int *bottom);
- void left_to_right(unsigned char *bytes, int width, int height, int *left, int *right);
- void memprint(FILE *stream, size_t nbytes, const void *src);
- int main(int argc, char **argv) {
- FILE *log_file = fopen("log.txt", "a+");
- fprintf(log_file, "---------------------------------------\n");
- for (int i=0; i<argc; ++i) {
- fprintf(log_file, "argv[%d]: %s\n", i, argv[i]);
- }
- if (argc > 1) {
- for (int n = 1; n < argc; ++n) {
- clock_t start = clock(), diff;
- // convert backslash separated path to forward slash separated
- memset(scratch, 0, SCRATCH_CAP);
- int length = 0;
- const char *c = argv[n];
- char prv = 0;
- while (*c) {
- if (*c == '\\') {
- if (prv == '\\') {
- scratch[length++] = *c;
- } else {
- scratch[length++] = '/';
- }
- } else {
- scratch[length++] = *c;
- }
- prv = *c;
- c++;
- }
- const char *name = strrchr(argv[n], '/');
- if (!name) {
- name = argv[n];
- }
- const int name_len = strlen(name);
- int width, height, components;
- unsigned char *bytes = stbi_load(argv[n], &width, &height, &components, 0);
- fprintf(stderr, "%s: %d %d %d\n", name, width, height, components);
- int top, bottom;
- int left, right;
- top_to_bottom(bytes, width, height, &top, &bottom);
- left_to_right(bytes, width, height, &left, &right);
- int new_width = right - left;
- int new_height = bottom - top;
- fprintf(stderr, "left right top bottom: %d %d %d %d\n", left, right, top, bottom);
- fprintf(log_file, "INFO: new dimensions (%d %d)\n", new_width, new_height);
- int invalid_image = 0;
- if (new_width <= 0 || new_height <= 0) {
- fprintf(stderr, "ERROR: invalid new dimensions. (%d %d)\n", new_width, new_height);
- fprintf(log_file, "ERROR: invalid new dimensions. (%d %d)\n", new_width, new_height);
- new_width = 256;
- new_height = 256;
- invalid_image = 1;
- }
- size_t pixel_count = new_width * new_height;
- Pixel *buffer = malloc(pixel_count * sizeof(Pixel));
- if (!invalid_image) {
- Pixel *source = (Pixel*)bytes;
- int m = 0;
- for (int j = top; j < bottom; ++j) {
- for (int i = left; i < right; ++i) {
- buffer[m++] = source[j*width+i];
- }
- }
- } else {
- for (size_t i = 0; i < pixel_count; ++i) {
- buffer[i] = (Pixel){255,0,255};
- }
- }
- // Handling the output filename and path. This is terrible; there has to be a better way.
- char *filename_sep = strrchr(scratch, '/');
- if (filename_sep) {
- memmove(filename_sep + sizeof(out_folder), filename_sep, strlen(filename_sep));
- memcpy(filename_sep+1, out_folder, sizeof(out_folder)-1);
- } else {
- //int name_len = strlen(scratch);
- memmove(scratch + sizeof(out_folder) + 2, scratch, name_len);
- scratch[sizeof(out_folder)+1] = '/';
- memcpy(scratch+2, out_folder, sizeof(out_folder)-1);
- scratch[0] = '.';
- scratch[1] = '/';
- }
- fprintf(log_file, "INFO: final path '%s'\n", scratch);
- stbi_write_jpg(scratch, new_width, new_height, components, (char*)buffer, 0);
- free(buffer);
- diff = clock() - start;
- int msec = diff * 1000 / CLOCKS_PER_SEC;
- fprintf(log_file, "INFO: TIME: %d s %d ms\n", msec/1000, msec%1000);
- }
- }
- fflush(log_file);
- fclose(log_file);
- return 0;
- }
- void top_to_bottom(unsigned char *bytes, int width, int height, int *top, int *bottom) {
- *top = 0;
- *bottom = 0;
- int max_brightness = width * 255 * 3;
- int peak = -max_brightness;
- int trough = max_brightness;
- int prv = max_brightness;
- Pixel *pixels = (Pixel*)bytes;
- for (int j = 0; j < height; ++j) {
- int cur = 0;
- for (int i = 0; i < width; ++i) {
- Pixel p = pixels[j*width+i];
- cur += p.r + p.g + p.b;
- }
- int delta = cur - prv;
- if (trough > delta) {
- trough = delta;
- *top = j;
- }
- if (peak < delta) {
- peak = delta;
- *bottom = j;
- }
- prv = cur;
- }
- if (peak < max_brightness - prv) {
- *bottom = height-1;
- }
- return;
- }
- void left_to_right(unsigned char *bytes, int width, int height, int *left, int *right) {
- *left = 0;
- *right = width;
- int max_brightness = height * 255 * 3;
- int peak = -max_brightness;
- int trough = max_brightness;
- int prv = max_brightness;
- Pixel *pixels = (Pixel*)bytes;
- for (int i = 0; i < width; ++i) {
- int cur = 0;
- for (int j = 0; j < height; ++j) {
- Pixel p = pixels[j*width+i];
- cur += p.r + p.g + p.b;
- }
- int delta = cur - prv;
- if (trough > delta) {
- trough = delta;
- *left = i;
- }
- if (peak < delta) {
- peak = delta;
- *right = i;
- }
- prv = cur;
- }
- if (peak < max_brightness - prv) {
- *right = width-1;
- }
- return;
- }
- void memprint(FILE *stream, size_t nbytes, const void *src) {
- const char *mem = (char*)src;
- for (size_t i = 0; i < nbytes; ++i) {
- char letter = mem[i];
- if (!isprint(letter)) letter = '.';
- fprintf(stream, "%c", letter);
- }
- }
Add Comment
Please, Sign In to add comment