Munashedov

Autocrop

Apr 6th, 2023
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.69 KB | Source Code | 0 0
  1. // Autocrop by Munashe
  2. // 4-6-2023
  3. // Drag and drop scanned photoes onto the exe to automatically crop them.
  4. // Only supports jpeg
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10.  
  11. #include <time.h>
  12.  
  13. #ifdef __linux__
  14.     #include <sys/types.h>
  15.     #include <dirent.h>
  16. #elif _WIN32
  17.     #define WIN32_LEAN_AND_MEAN
  18.     #include <windows.h>
  19.     #define mkdir(dir, mode) _mkdir(dir)
  20. #else
  21.     // unsupported
  22. #endif
  23.  
  24. #define STB_IMAGE_IMPLEMENTATION
  25. #include "stb_image.h"
  26.  
  27. #define STB_IMAGE_WRITE_IMPLEMENTATION
  28. #include "stb_image_write.h"
  29.  
  30. #define THRESHOLD 600
  31.  
  32. #define SCRATCH_CAP 1024
  33. char scratch[SCRATCH_CAP] = {0};
  34.  
  35. const char out_folder[] = "output";
  36.  
  37. typedef struct Pixel { unsigned char r; unsigned char g; unsigned char b; } Pixel;
  38.  
  39. void top_to_bottom(unsigned char *bytes, int width, int height, int *top, int *bottom);
  40. void left_to_right(unsigned char *bytes, int width, int height, int *left, int *right);
  41.  
  42. void memprint(FILE *stream, size_t nbytes, const void *src);
  43.  
  44. int main(int argc, char **argv) {
  45.     FILE *log_file = fopen("log.txt", "a+");
  46.     fprintf(log_file, "---------------------------------------\n");
  47.     for (int i=0; i<argc; ++i) {
  48.         fprintf(log_file, "argv[%d]: %s\n", i, argv[i]);
  49.     }
  50.     if (argc > 1) {
  51.         for (int n = 1; n < argc; ++n) {
  52.             clock_t start = clock(), diff;
  53.            
  54.             // convert backslash separated path to forward slash separated
  55.             memset(scratch, 0, SCRATCH_CAP);
  56.             int length = 0;
  57.             const char *c = argv[n];
  58.             char prv = 0;
  59.             while (*c) {
  60.                 if (*c == '\\') {
  61.                     if (prv == '\\') {
  62.                         scratch[length++] = *c;
  63.                     } else {
  64.                         scratch[length++] = '/';
  65.                     }
  66.                 } else {
  67.                     scratch[length++] = *c;
  68.                 }
  69.                 prv = *c;
  70.                 c++;
  71.             }
  72.             const char *name = strrchr(argv[n], '/');
  73.             if (!name) {
  74.                 name = argv[n];
  75.             }
  76.             const int name_len = strlen(name);
  77.            
  78.             int width, height, components;
  79.             unsigned char *bytes = stbi_load(argv[n], &width, &height, &components, 0);
  80.             fprintf(stderr, "%s: %d %d %d\n", name, width, height, components);
  81.             int top, bottom;
  82.             int left, right;
  83.             top_to_bottom(bytes, width, height, &top, &bottom);
  84.             left_to_right(bytes, width, height, &left, &right);
  85.             int new_width  = right  - left;
  86.             int new_height = bottom - top;
  87.             fprintf(stderr, "left right top bottom: %d %d %d %d\n", left, right, top, bottom);
  88.             fprintf(log_file, "INFO: new dimensions (%d %d)\n", new_width, new_height);
  89.             int invalid_image = 0;
  90.             if (new_width <= 0 || new_height <= 0) {
  91.                 fprintf(stderr, "ERROR: invalid new dimensions. (%d %d)\n", new_width, new_height);
  92.                 fprintf(log_file, "ERROR: invalid new dimensions. (%d %d)\n", new_width, new_height);
  93.                 new_width  = 256;
  94.                 new_height = 256;
  95.                 invalid_image = 1;
  96.             }
  97.             size_t pixel_count = new_width * new_height;
  98.             Pixel *buffer = malloc(pixel_count * sizeof(Pixel));
  99.             if (!invalid_image) {
  100.                 Pixel *source = (Pixel*)bytes;
  101.                 int m = 0;
  102.                 for (int j = top; j < bottom; ++j) {
  103.                     for (int i = left; i < right; ++i) {
  104.                         buffer[m++] = source[j*width+i];
  105.                     }
  106.                 }
  107.             } else {
  108.                 for (size_t i = 0; i < pixel_count; ++i) {
  109.                     buffer[i] = (Pixel){255,0,255};
  110.                 }
  111.             }
  112.            
  113.             // Handling the output filename and path. This is terrible; there has to be a better way.
  114.             char *filename_sep = strrchr(scratch, '/');
  115.             if (filename_sep) {
  116.                 memmove(filename_sep + sizeof(out_folder), filename_sep, strlen(filename_sep));
  117.                 memcpy(filename_sep+1, out_folder, sizeof(out_folder)-1);
  118.             } else {
  119.                 //int name_len = strlen(scratch);
  120.                 memmove(scratch + sizeof(out_folder) + 2, scratch, name_len);
  121.                 scratch[sizeof(out_folder)+1] = '/';
  122.                 memcpy(scratch+2, out_folder, sizeof(out_folder)-1);
  123.                 scratch[0] = '.';
  124.                 scratch[1] = '/';
  125.             }
  126.             fprintf(log_file, "INFO: final path '%s'\n", scratch);
  127.             stbi_write_jpg(scratch, new_width, new_height, components, (char*)buffer, 0);
  128.            
  129.             free(buffer);
  130.            
  131.             diff = clock() - start;
  132.             int msec = diff * 1000 / CLOCKS_PER_SEC;
  133.             fprintf(log_file, "INFO: TIME: %d s %d ms\n", msec/1000, msec%1000);
  134.         }
  135.     }
  136.     fflush(log_file);
  137.     fclose(log_file);
  138.     return 0;
  139. }
  140.  
  141. void top_to_bottom(unsigned char *bytes, int width, int height, int *top, int *bottom) {
  142.     *top = 0;
  143.     *bottom = 0;
  144.     int max_brightness = width * 255 * 3;
  145.     int peak   = -max_brightness;
  146.     int trough = max_brightness;
  147.     int prv = max_brightness;
  148.     Pixel *pixels = (Pixel*)bytes;
  149.     for (int j = 0; j < height; ++j) {
  150.         int cur = 0;
  151.         for (int i = 0; i < width; ++i) {
  152.             Pixel p = pixels[j*width+i];
  153.             cur += p.r + p.g + p.b;
  154.         }
  155.         int delta = cur - prv;
  156.         if (trough > delta) {
  157.             trough = delta;
  158.             *top = j;
  159.         }
  160.         if (peak < delta) {
  161.             peak = delta;
  162.             *bottom = j;
  163.         }
  164.         prv = cur;
  165.     }
  166.     if (peak < max_brightness - prv) {
  167.         *bottom = height-1;
  168.     }
  169.     return;
  170. }
  171.  
  172. void left_to_right(unsigned char *bytes, int width, int height, int *left, int *right) {
  173.     *left = 0;
  174.     *right = width;
  175.     int max_brightness = height * 255 * 3;
  176.     int peak   = -max_brightness;
  177.     int trough = max_brightness;
  178.     int prv = max_brightness;
  179.     Pixel *pixels = (Pixel*)bytes;
  180.     for (int i = 0; i < width; ++i) {
  181.         int cur = 0;
  182.         for (int j = 0; j < height; ++j) {
  183.             Pixel p = pixels[j*width+i];
  184.             cur += p.r + p.g + p.b;
  185.         }
  186.         int delta = cur - prv;
  187.  
  188.         if (trough > delta) {
  189.             trough = delta;
  190.             *left = i;
  191.         }
  192.         if (peak < delta) {
  193.             peak = delta;
  194.             *right = i;
  195.         }
  196.         prv = cur;
  197.     }
  198.     if (peak < max_brightness - prv) {
  199.         *right = width-1;
  200.     }
  201.     return;
  202. }
  203.  
  204. void memprint(FILE *stream, size_t nbytes, const void *src) {
  205.     const char *mem = (char*)src;
  206.     for (size_t i = 0; i < nbytes; ++i) {
  207.         char letter = mem[i];
  208.         if (!isprint(letter)) letter = '.';
  209.         fprintf(stream, "%c", letter);
  210.     }
  211. }
  212.  
Add Comment
Please, Sign In to add comment