Advertisement
jcdkiki

Untitled

Apr 30th, 2024
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 18.27 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <getopt.h>
  4. #include <string.h>
  5. #include <limits.h>
  6.  
  7. #pragma pack(push, 1)
  8.  
  9. #define CW_OK 0
  10. #define CW_ERROR 40
  11.  
  12. enum {
  13.     EXCHANGE_UNKNOWN = -1,
  14.     EXCHANGE_CLOCKWISE = 0,
  15.     EXCHANGE_COUNTERCLOCKWISE,
  16.     EXCHANGE_DIAGONALS
  17. };
  18.  
  19. typedef struct {
  20.     unsigned short signature;
  21.     unsigned int filesize;
  22.     unsigned short reserved1;
  23.     unsigned short reserved2;
  24.     unsigned int data_offset;
  25. } bmpfile_header_t;
  26.  
  27. typedef struct {
  28.     unsigned int header_size;
  29.     unsigned int width;
  30.     unsigned int height;
  31.     unsigned short planes;
  32.     unsigned short bits_per_pixel;
  33.     unsigned int compression;
  34.     unsigned int image_size;
  35.     unsigned int xresolution;
  36.     unsigned int yresolution;
  37.     unsigned int n_colors;
  38.     unsigned int n_important_colors;
  39. } bmpfile_info_t;
  40.  
  41. typedef struct {
  42.     unsigned char b;
  43.     unsigned char g;
  44.     unsigned char r;
  45. } rgb_t;
  46.  
  47. #pragma pack(pop)
  48.  
  49. typedef struct {
  50.     int x, y;
  51. } point_t;
  52.  
  53. typedef struct {
  54.     bmpfile_header_t header;
  55.     bmpfile_info_t   info;
  56.     rgb_t**          data;
  57. } bmp_t;
  58.  
  59. int load_bmp(bmp_t *bmp, char *filename)
  60. {
  61.     FILE *fp = fopen(filename, "rb");
  62.     if (fp == NULL) {
  63.         fputs("Cannot open input file\n", stderr);
  64.         return CW_ERROR;
  65.     }
  66.  
  67.     fread(&bmp->header, 1, sizeof(bmpfile_header_t), fp);
  68.     fread(&bmp->info, 1, sizeof(bmpfile_info_t), fp);
  69.  
  70.     if (bmp->header.signature!= 0x4D42) {
  71.         fputs("Invalid file signature\n", stderr);
  72.         fclose(fp);
  73.         return CW_ERROR;
  74.     }
  75.  
  76.     if (bmp->info.bits_per_pixel != 24 || bmp->info.compression != 0 || bmp->info.planes != 1) {
  77.         fputs("Unsupported BMP format\n", stderr);
  78.         fclose(fp);
  79.         return CW_ERROR;
  80.     }
  81.  
  82.     bmp->data = (rgb_t**)malloc(bmp->info.height * sizeof(rgb_t*));
  83.     if (bmp->data == NULL) {
  84.         fputs("Memory allocation error\n", stderr);
  85.         fclose(fp);
  86.         return CW_ERROR;
  87.     }
  88.  
  89.     size_t padding = (4 - (sizeof(bmp_t) * bmp->info.width) % 4) % 4;
  90.    
  91.     for (int i = bmp->info.height - 1; i >= 0; i--) {
  92.         bmp->data[i] = (rgb_t*)malloc(bmp->info.width * sizeof(rgb_t));
  93.         if (bmp->data[i] == NULL) {
  94.             fputs("Memory allocation error\n", stderr);
  95.             fclose(fp);
  96.  
  97.             for (size_t j = bmp->info.height - 1; j > i; j--)
  98.                 free(bmp->data[j]);
  99.             free(bmp->data);
  100.             return CW_ERROR;
  101.         }
  102.  
  103.         fread(bmp->data[i], 1, bmp->info.width * sizeof(rgb_t), fp);
  104.         fseek(fp, padding, SEEK_CUR);
  105.     }
  106.  
  107.     fclose(fp);
  108.     return CW_OK;
  109. }
  110.  
  111. int save_bmp(bmp_t *bmp, char *filename)
  112. {
  113.     FILE *fp = fopen(filename, "wb");
  114.     if (fp == NULL) {
  115.         fputs("Cannot open output file\n", stderr);
  116.         return CW_ERROR;
  117.     }
  118.  
  119.     fwrite(&bmp->header, 1, sizeof(bmpfile_header_t), fp);
  120.     fwrite(&bmp->info, 1, sizeof(bmpfile_info_t), fp);
  121.     fseek(fp, bmp->header.data_offset, SEEK_SET);
  122.  
  123.     size_t padding = (4 - (4 * bmp->info.width) % 4) % 4;
  124.     for (int i = bmp->info.height - 1; i >= 0; i--) {
  125.         fwrite(bmp->data[i], 1, bmp->info.width * sizeof(rgb_t), fp);
  126.         fseek(fp, padding, SEEK_CUR);
  127.     }
  128.  
  129.     fclose(fp);
  130.     return CW_OK;
  131. }
  132.  
  133. void free_bmp(bmp_t *bmp)
  134. {
  135.     for (size_t i = 0; i < bmp->info.height; i++) {
  136.         free(bmp->data[i]);
  137.     }
  138.     free(bmp->data);
  139. }
  140.  
  141. const char shortopts[] = "hil:s:t:c:fF:r:x:I:O:";
  142.  
  143. enum {
  144.     FUNCTION_SQUARE = 1,
  145.     FUNCTION_EXCHANGE,
  146.     FUNCTION_FREQ_COLOR
  147. };
  148.  
  149. struct option longopts[] = {
  150.     { "help", 0, NULL, 'h' },
  151.     { "info", 0, NULL, 'i' },
  152.     { "square", 0, NULL, FUNCTION_SQUARE },
  153.     { "exchange", 0, NULL, FUNCTION_EXCHANGE },
  154.     { "freq_color", 0, NULL, FUNCTION_FREQ_COLOR },
  155.  
  156.     { "left_up", 1, NULL, 'l' },
  157.     { "side_size", 1, NULL,'s' },
  158.     { "thickness", 1, NULL, 't' },
  159.     { "color", 1, NULL, 'c'},
  160.     { "fill", 0, NULL, 'f' },
  161.     { "fill_color", 1, NULL, 'F' },
  162.  
  163.     { "right_down", 1, NULL, 'r' },
  164.     { "exchange_type", 1, NULL, 'x' },
  165.  
  166.     { "input", 1, NULL, 'I' },
  167.     { "output", 1, NULL, 'O' },
  168.  
  169.     { NULL, 0, NULL, 0 }
  170. };
  171.  
  172. typedef struct {
  173.     point_t left_up;
  174.     int side_size;
  175.     int thickness;
  176.     rgb_t color;
  177.     char is_color_set;
  178.     char fill;
  179.     rgb_t fill_color;
  180.     char is_fill_color_set;
  181.     point_t right_down;
  182.     int exchange_type;
  183.     char *input;
  184.     char *output;
  185. } args_t;
  186.  
  187. void init_args(args_t *args)
  188. {
  189.     args->left_up = (point_t) { INT_MAX, INT_MAX };
  190.     args->side_size = INT_MAX;
  191.     args->thickness = INT_MAX;
  192.     args->color = (rgb_t) { 0, 0, 0 };
  193.     args->is_color_set = 0;
  194.     args->fill = 0;
  195.     args->right_down = (point_t) { INT_MAX, INT_MAX };
  196.     args->exchange_type = EXCHANGE_UNKNOWN;
  197.     args->input = NULL;
  198.     args->output = "out.bmp";
  199. }
  200.  
  201. int read_color(rgb_t *rgb, char *str)
  202. {
  203.     int r, g, b;
  204.     int n = sscanf(str, "%d.%d.%d", &r, &g, &b);
  205.  
  206.     if (n != 3) {
  207.         fputs("Invalid color format\n", stderr);
  208.         return CW_ERROR;
  209.     }
  210.  
  211.     if (r < 0 || g < 0 || b < 0 || r > 255 || g > 255 || b > 255) {
  212.         fputs("Invalid color value\n", stderr);
  213.         return CW_ERROR;
  214.     }
  215.  
  216.     rgb->r = r;
  217.     rgb->g = g;
  218.     rgb->b = b;
  219.     return CW_OK;
  220. }
  221.  
  222. int read_int(int *val, char *str)
  223. {
  224.     int n = sscanf(str, "%d", val);
  225.  
  226.     if (n != 1) {
  227.         fputs("Invalid integer\n", stderr);
  228.         return CW_ERROR;
  229.     }
  230.  
  231.     return CW_OK;
  232. }
  233.  
  234. int read_point(point_t *pt, char *str)
  235. {
  236.     int n = sscanf(str, "%d.%d", &pt->x, &pt->y);
  237.    
  238.     if (n!= 2) {
  239.         fputs("Invalid point format\n", stderr);
  240.         return CW_ERROR;
  241.     }
  242.  
  243.     return CW_OK;
  244. }
  245.  
  246. int read_exchange_type(int *exchange_type, char *str)
  247. {
  248.     if (strcmp(str, "clockwise") == 0) {
  249.         *exchange_type = EXCHANGE_CLOCKWISE;
  250.         return CW_OK;
  251.     }
  252.     if (strcmp(str, "counterclockwise") == 0) {
  253.         *exchange_type = EXCHANGE_COUNTERCLOCKWISE;
  254.         return CW_OK;
  255.     }
  256.     if (strcmp(str, "diagonals") == 0) {
  257.         *exchange_type = EXCHANGE_DIAGONALS;
  258.         return CW_OK;
  259.     }
  260.  
  261.     fputs("Invalid exchange type\n", stderr);
  262.     return CW_ERROR;  
  263. }
  264.  
  265. void print_help()
  266. {
  267.     puts(
  268.         "./cw <function> [options]\n"
  269.         "Functions:\n"
  270.         " -h, --help\n"
  271.         " -i, --info     print info about image\n"
  272.         " --square       draw square\n"
  273.         " --exchange     exchange four pieces of the image\n"
  274.         " --freq_color   replace most frequent color\n"
  275.         "Options:\n"
  276.         " -I, --input <file>\n"
  277.         " -O, --output <file>\n"
  278.         "Options for square:\n"
  279.         " -l, --left_up X.Y\n"
  280.         " -s, --side_size X\n"
  281.         " -t, --thickness X\n"
  282.         " -c, --color R.G.B\n"
  283.         " -f, --fill (flag to fill the square)\n"
  284.         " -F, --fill_color R.G.B\n"
  285.         "Options for exchange:\n"
  286.         "  -x, --exchange_type (clockwise, counterclockwise, diagonals)\n"
  287.         "  -l, --left_up X.Y\n"
  288.         "  -r, --right_down X.Y\n"
  289.         "Options for freq_color:\n"
  290.         "  -c, --color R.G.B"
  291.     );
  292. }
  293.  
  294. rgb_t get_pixel(bmp_t *bmp, int x, int y)
  295. {
  296.     if (x < 0 || y < 0 || x >= (int)bmp->info.width || y >= (int)bmp->info.height) {
  297.         return (rgb_t) { 0, 0, 0 };
  298.     }
  299.     return bmp->data[y][x];
  300. }
  301.  
  302. void set_pixel(bmp_t *bmp, int x, int y, rgb_t rgb)
  303. {
  304.     if (x < 0 || y < 0 || x >= (int)bmp->info.width || y >= (int)bmp->info.height)
  305.         return;
  306.     bmp->data[y][x] = rgb;
  307. }
  308.  
  309. int print_image_info_option(bmp_t *bmp)
  310. {
  311.     printf("Width: %d\n", (int)bmp->info.width);
  312.     printf("Height: %d\n", (int)bmp->info.height);
  313.     printf("Planes: %d\n", (int)bmp->info.planes);
  314.     printf("Bits per pixel: %d\n", (int)bmp->info.bits_per_pixel);
  315.     printf("Compression: %d\n", (int)bmp->info.compression);
  316.     printf("Image size: %d\n", (int)bmp->info.image_size);
  317.     printf("X resolution: %d\n", (int)bmp->info.xresolution);
  318.     printf("Y resolution: %d\n", (int)bmp->info.yresolution);
  319.     printf("Number of colors: %d\n", (int)bmp->info.n_colors);
  320.     printf("Number of important colors: %d\n", (int)bmp->info.n_important_colors);
  321.  
  322.     return CW_OK;
  323. }
  324.  
  325. int draw_square_option(bmp_t *bmp, args_t *args)
  326. {
  327.     if (args->left_up.x == INT_MAX && args->left_up.y == INT_MAX) {
  328.         fputs("Left up corner not specified\n", stderr);
  329.         return CW_ERROR;
  330.     }
  331.     if (args->side_size == INT_MAX) {
  332.         fputs("Side size not specified\n", stderr);
  333.         return CW_ERROR;
  334.     }
  335.     if (args->thickness == INT_MAX) {
  336.         fputs("Thickness not specified\n", stderr);
  337.         return CW_ERROR;
  338.     }
  339.     if (args->is_color_set == 0) {
  340.         fputs("Color not specified\n", stderr);
  341.         return CW_ERROR;
  342.     }
  343.     if (args->fill == 1 && args->is_fill_color_set == 0) {
  344.         fputs("Fill color not specified\n", stderr);
  345.         return CW_ERROR;
  346.     }
  347.  
  348.     int x0 = args->left_up.x;
  349.     int y0 = args->left_up.y;
  350.     int x1 = args->left_up.x + args->side_size;
  351.     int y1 = args->left_up.y + args->side_size;
  352.  
  353.     args->thickness = (args->thickness + 1) / 2;
  354.  
  355.     if (args->fill) {
  356.         int fx0 = (x0 < 0) ? 0 : x0;
  357.         int fy0 = (y0 < 0) ? 0 : y0;
  358.         int fx1 = (x1 > (int)bmp->info.width) ? (int)bmp->info.width : x1;
  359.         int fy1 = (y1 > (int)bmp->info.height) ? (int)bmp->info.height : y1;
  360.  
  361.         for (int x = fx0; x < fx1; x++) {
  362.             for (int y = fy0; y < fy1; y++) {
  363.                 set_pixel(bmp, x, y, args->fill_color);
  364.             }
  365.         }
  366.     }
  367.  
  368.     for (int s = -args->thickness+1; s < args->side_size + args->thickness; s++) {
  369.         for (int t = 0; t < args->thickness; t++) {
  370.             set_pixel(bmp, x0 + s, y0 + t, args->color);
  371.             set_pixel(bmp, x0 + s, y0 - t, args->color);
  372.             set_pixel(bmp, x0 + t, y0 + s, args->color);
  373.             set_pixel(bmp, x0 - t, y0 + s, args->color);
  374.             set_pixel(bmp, x0 + s, y1 + t, args->color);
  375.             set_pixel(bmp, x0 + s, y1 - t, args->color);
  376.             set_pixel(bmp, x1 + t, y0 + s, args->color);
  377.             set_pixel(bmp, x1 - t, y0 + s, args->color);
  378.         }
  379.     }
  380.  
  381.     return CW_OK;
  382. }
  383.  
  384. void swap_regions(bmp_t *bmp, int x0, int y0, int x1, int y1, int dx, int dy)
  385. {
  386.     for (int x = 0; x < dx; x++) {
  387.         for (int y = 0; y < dy; y++) {
  388.             rgb_t tmp = get_pixel(bmp, x0 + x, y0 + y);
  389.             set_pixel(bmp, x0 + x, y0 + y, get_pixel(bmp, x1 + x, y1 + y));
  390.             set_pixel(bmp, x1 + x, y1 + y, tmp);
  391.         }
  392.     }
  393. }
  394.  
  395. int exchange_opion(bmp_t *bmp, args_t *args)
  396. {
  397.     if (args->exchange_type == EXCHANGE_UNKNOWN) {
  398.         fputs("Exchange type is not specified\n", stderr);
  399.         return CW_ERROR;
  400.     }
  401.     if (args->left_up.x == INT_MAX && args->left_up.y == INT_MAX) {
  402.         fputs("Left up point is not specified\n", stderr);
  403.         return CW_ERROR;
  404.     }
  405.     if (args->right_down.x == INT_MAX && args->right_down.y == INT_MAX) {
  406.         fputs("Right down point is not specified\n", stderr);
  407.         return CW_ERROR;
  408.     }
  409.  
  410.     int x0 = args->left_up.x;
  411.     int y0 = args->left_up.y;
  412.     int x1 = args->right_down.x;
  413.     int y1 = args->right_down.y;
  414.     int dx = (x1 - x0) / 2;
  415.     int dy = (y1 - y0) / 2;
  416.  
  417.     if (args->exchange_type == EXCHANGE_DIAGONALS) {
  418.         swap_regions(bmp, x0, y0, x0 + dx, y0 + dx, dx, dy);
  419.         swap_regions(bmp, x0 + dx, y0, x0, y0 + dx, dx, dy);    
  420.     }
  421.     else if (args->exchange_type == EXCHANGE_CLOCKWISE) {
  422.         swap_regions(bmp, x0, y0, x0, y0 + dy, dx, dy);
  423.         swap_regions(bmp, x0 + dx, y0, x0, y0 + dy, dx, dy);
  424.         swap_regions(bmp, x0 + dx, y0 + dy, x0, y0 + dy, dx, dy);
  425.     }
  426.     else {
  427.         swap_regions(bmp, x0, y0, x0 + dx, y0, dx, dy);
  428.         swap_regions(bmp, x0 + dx, y0, x0 + dx, y0 + dy, dx, dy);
  429.         swap_regions(bmp, x0 + dx, y0 + dy, x0, y0 + dy, dx, dy);
  430.     }
  431.  
  432.     return CW_OK;
  433. }
  434.  
  435. typedef struct {
  436.     rgb_t color;
  437.     size_t freq;
  438. } colorinfo_t;
  439.  
  440. #define BASE_SIZE 256
  441. #define MAX_SEARCH 10
  442.  
  443. int find_color(colorinfo_t *colors, size_t size, rgb_t color)
  444. {
  445.     for (size_t i = 0; i < size; i++) {
  446.         if (colors[i].color.r == color.r &&
  447.             colors[i].color.g == color.g &&
  448.             colors[i].color.b == color.b) {
  449.             return i;
  450.         }
  451.     }
  452.     return -1;
  453. }
  454.  
  455. int cantor_pairing(int a, int b)
  456. {
  457.    return (a + b + 1) * (a + b) / 2 + b;
  458. }
  459.  
  460. int hash_color(rgb_t color)
  461. {
  462.    return cantor_pairing(color.r, cantor_pairing(color.g, color.b));
  463. }
  464.  
  465. int colors_equal(rgb_t a, rgb_t b)
  466. {
  467.     return a.r == b.r && a.g == b.g && a.b == b.b;
  468. }
  469.  
  470. int increment_color(colorinfo_t *colors, size_t size, rgb_t color, int amount)
  471. {
  472.     int start_index = hash_color(color) % size;
  473.  
  474.     for (int i = 0; i < MAX_SEARCH; i++) {
  475.         int index = (start_index + i) % size;
  476.  
  477.         if (colors[index].freq > 0 && colors_equal(colors[index].color, color)) {
  478.             colors[index].freq += amount;
  479.             return 1;
  480.         }
  481.     }
  482.  
  483.     // try to insert
  484.     for (int i = 0; i < MAX_SEARCH; i++) {
  485.         int index = (start_index + i) % size;
  486.  
  487.         if (colors[index].freq == 0) {
  488.             colors[index].freq = 1;
  489.             colors[index].color = color;
  490.             return 1;
  491.         }
  492.     }
  493.    
  494.     return 0;
  495. }
  496.  
  497. colorinfo_t *grow_colors(colorinfo_t *old_colors, size_t old_size, size_t new_size, size_t *out_size)
  498. {
  499.     colorinfo_t *new_colors = (colorinfo_t*)malloc(sizeof(colorinfo_t) * new_size);
  500.     if (new_colors == NULL) {
  501.         fputs("Memory allocation failed\n", stderr);
  502.         free(old_colors);
  503.         return NULL;
  504.     }
  505.  
  506.     memset(new_colors, 0, sizeof(colorinfo_t) * new_size);
  507.  
  508.     for (size_t i = 0; i < old_size; i++) {
  509.         if (old_colors[i].freq > 0) {
  510.             if (!increment_color(new_colors, new_size, old_colors[i].color, old_colors[i].freq)) {
  511.                 free(new_colors);
  512.                 return grow_colors(old_colors, old_size, new_size * 2, out_size);
  513.             }
  514.         }
  515.     }
  516.  
  517.     *out_size = new_size;
  518.     free(old_colors);
  519.     return new_colors;
  520. }
  521.  
  522. int freq_color_option(bmp_t *bmp, args_t *args)
  523. {
  524.     if (!args->is_color_set) {
  525.         fputs("Color is not specified\n", stderr);
  526.         return CW_ERROR;
  527.     }
  528.  
  529.     colorinfo_t *colors = malloc(sizeof(colorinfo_t) * BASE_SIZE);
  530.  
  531.     if (colors == NULL) {
  532.         fputs("Memory allocation failed\n", stderr);
  533.         return CW_ERROR;
  534.     }
  535.  
  536.     size_t size = BASE_SIZE;
  537.     memset(colors, 0, sizeof(colorinfo_t) * BASE_SIZE);
  538.    
  539.     for (int y = 0; y < (int)bmp->info.height; y++) {
  540.         for (int x = 0; x < (int)bmp->info.width; x++) {
  541.             int ret = increment_color(colors, size, get_pixel(bmp, x, y), 1);
  542.             while (!ret) {
  543.                 size_t new_size;
  544.                 colors = grow_colors(colors, size, size * 2, &new_size);
  545.                 if (colors == NULL)
  546.                     return CW_ERROR;
  547.  
  548.                 size = new_size;
  549.                 ret = increment_color(colors, size, get_pixel(bmp, x, y), 1);
  550.             }
  551.         }
  552.     }
  553.  
  554.     int best_i = 0;
  555.     for (size_t i = 0; i < size; i++) {
  556.         if (colors[i].freq > colors[best_i].freq)
  557.             best_i = i;
  558.     }
  559.  
  560.     rgb_t color = colors[best_i].color;
  561.     for (int y = 0; y < (int)bmp->info.height; y++) {
  562.         for (int x = 0; x < (int)bmp->info.width; x++) {
  563.             if (bmp->data[y][x].r == color.r &&
  564.                 bmp->data[y][x].g == color.g &&
  565.                 bmp->data[y][x].b == color.b) {
  566.                 bmp->data[y][x] = args->color;
  567.             }
  568.         }
  569.     }
  570.  
  571.     free(colors);
  572.     return CW_OK;
  573. }
  574.  
  575. int main(int argc, char **argv)
  576. {
  577.     puts("Course work for option 4.4, created by Kulach Daniil");
  578.  
  579.     args_t args;
  580.     int function = '\0';
  581.  
  582.     init_args(&args);
  583.  
  584.     int opt = getopt_long(argc, argv, shortopts, longopts, NULL);
  585.     while (opt!= -1) {
  586.         if (opt == '?') {
  587.             fputs("Invalid option\n", stderr);
  588.             return CW_ERROR;
  589.         }
  590.  
  591.         int ret = CW_OK;
  592.         switch (opt) {
  593.             case 'h':
  594.                 print_help();
  595.                 return CW_OK;
  596.             case 'i':
  597.             case FUNCTION_SQUARE:
  598.             case FUNCTION_EXCHANGE:
  599.             case FUNCTION_FREQ_COLOR:
  600.                 function = opt;
  601.                 break;
  602.             case 'l':
  603.                 ret = read_point(&args.left_up, optarg);
  604.                 break;
  605.             case 's':
  606.                 ret = read_int(&args.side_size, optarg);
  607.                 break;
  608.             case 't':
  609.                 ret = read_int(&args.thickness, optarg);
  610.                 break;
  611.             case 'c':
  612.                 ret = read_color(&args.color, optarg);
  613.                 args.is_color_set = 1;
  614.                 break;
  615.             case 'f':
  616.                 args.fill = 1;
  617.                 break;
  618.             case 'F':
  619.                 ret = read_color(&args.fill_color, optarg);
  620.                 args.is_fill_color_set = 1;
  621.             case 'r':
  622.                 ret = read_point(&args.right_down, optarg);
  623.                 break;
  624.             case 'x':
  625.                 ret = read_exchange_type(&args.exchange_type, optarg);
  626.                 break;
  627.             case 'I':
  628.                 args.input = optarg;
  629.                 break;
  630.             case 'O':
  631.                 args.output = optarg;
  632.                 break;
  633.         }
  634.  
  635.         if (ret != CW_OK) {
  636.             return CW_ERROR;
  637.         }
  638.  
  639.         opt = getopt_long(argc, argv, shortopts, longopts, NULL);
  640.     }
  641.  
  642.     if (function == '\0') {
  643.         fputs("No function specified\n", stderr);
  644.         return CW_ERROR;
  645.     }
  646.  
  647.     if (args.input == NULL) {
  648.         if (optind >= argc) {
  649.             fputs("No image specified\n", stderr);
  650.             return CW_ERROR;
  651.         }
  652.         args.input = argv[optind];
  653.     }
  654.  
  655.     bmp_t bmp;
  656.     if (load_bmp(&bmp, args.input) != CW_OK) {
  657.         return CW_ERROR;
  658.     }
  659.  
  660.     int ret = CW_OK;
  661.     switch (function) {
  662.         case 'i':
  663.             ret = print_image_info_option(&bmp);
  664.             break;
  665.         case FUNCTION_SQUARE:
  666.             ret = draw_square_option(&bmp, &args);
  667.             break;
  668.         case FUNCTION_EXCHANGE:
  669.             ret = exchange_opion(&bmp, &args);
  670.             break;
  671.         case FUNCTION_FREQ_COLOR:
  672.             ret = freq_color_option(&bmp, &args);
  673.             break;
  674.     }
  675.  
  676.     if (ret != CW_OK) {
  677.         free_bmp(&bmp);
  678.         return CW_ERROR;
  679.     }
  680.  
  681.     if (function != 'i') {
  682.         int ret = save_bmp(&bmp, args.output);
  683.         if (ret != CW_OK) {
  684.             return CW_ERROR;
  685.         }
  686.     }
  687.  
  688.     free_bmp(&bmp);
  689. }
  690.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement