Advertisement
jcdkiki

Untitled

May 27th, 2024
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.10 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <assert.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <getopt.h>
  8.  
  9. #define FAILURE -1
  10. #define SUCCESS 0
  11. #define EXIT_CW_FAILURE 40
  12. #define EXIT_CW_OK 0
  13.  
  14. typedef struct bmp_header {
  15.     uint16_t signature;
  16.     uint32_t filesize;
  17.     uint32_t reserved;
  18.     uint32_t data_offset;
  19. } __attribute__((packed)) bmp_header_t;
  20.  
  21. typedef struct info_header {
  22.     uint32_t size;
  23.     uint32_t width;
  24.     uint32_t height;
  25.     uint16_t planes;
  26.     uint16_t bit_count;
  27.     uint32_t compression;
  28.     uint32_t image_size;
  29.     uint32_t x_pixels_per_meter;
  30.     uint32_t y_pixels_per_meter;
  31.     uint32_t colors_used;
  32.     uint32_t colors_important;
  33. } __attribute__((packed)) bmp_infoheader_t;
  34.  
  35. typedef struct {
  36.     uint8_t b, g, r;
  37. } pixel_t;
  38.  
  39. typedef struct image {
  40.     bmp_infoheader_t info;
  41.     pixel_t *data;
  42. } image_t;
  43. //-------------------------------------------------------------------
  44.  
  45. int load_bmp(image_t *image, const char *filename)
  46. {
  47.     FILE *fp = fopen(filename, "rb");
  48.     if (fp == NULL) {
  49.         fprintf(stderr, "error: failed to open\n");
  50.         return FAILURE;
  51.     }
  52.  
  53.     bmp_header_t header;
  54.  
  55.     int n_read = fread(&header, 1, sizeof(header), fp);
  56.     if (n_read != sizeof(bmp_header_t)) {
  57.         fprintf(stderr, "error: failed to read bmp header\n");
  58.         fclose(fp);
  59.         return FAILURE;
  60.     }
  61.  
  62.     n_read = fread(&image->info, 1, sizeof(bmp_infoheader_t), fp);
  63.     if (n_read != sizeof(bmp_infoheader_t)) {
  64.         fprintf(stderr, "error: failed to read bmp info header\n");
  65.         fclose(fp);
  66.         return FAILURE;
  67.     }
  68.  
  69.     if (header.signature != 0x4D42) {
  70.         fprintf(stderr, "error: invalid bmp signature\n");
  71.         fclose(fp);
  72.         return FAILURE;
  73.  
  74.     }
  75.  
  76.     if  (image->info.bit_count != 24 || image->info.compression != 0) {
  77.         fprintf(stderr, "error: unsupported bmp format\n");
  78.         fclose(fp);
  79.         return FAILURE;
  80.     }
  81.  
  82.     fseek(fp, header.data_offset, SEEK_SET);
  83.  
  84.     image->data = (pixel_t*)malloc(sizeof(pixel_t) * image->info.width * image->info.height);
  85.     if (image->data == NULL) {
  86.         fprintf(stderr, "error: not enough memory");
  87.         fclose(fp);
  88.         return FAILURE;
  89.     }
  90.  
  91.     fread(image->data, 1, sizeof(pixel_t) * image->info.width * image->info.height, fp);
  92.  
  93.     fclose(fp);
  94.     return SUCCESS;
  95. }
  96.  
  97. struct option longopts[] = {
  98.     { "help",          0, NULL, 'h' },
  99.     { "info",          0, NULL, 'i' },
  100.     { "rgbfilter", 0, NULL, 'R' },
  101.     { "fill",         0, NULL, 'F' },
  102.     { "component_name", 1, NULL, 'n' },
  103.     { "max",     0, NULL, 'M' },
  104.     { "min",     0, NULL, 'm' },
  105.     { "color",         1, NULL, 'c' },
  106.     { "input",         1, NULL, '>' },
  107.     { "output",        1, NULL, '<' },
  108.     {NULL, 0, NULL, 0}
  109. };
  110.  
  111. #define OPTION_COMPONENT_NAME 1
  112. #define OPTION_FILTER 2
  113. #define OPTION_COLOR 4
  114.  
  115. typedef struct {
  116.     int flags;
  117.     char *component_name;
  118.     char *m_component;
  119.     pixel_t color;
  120.     char *input;
  121.     char *output;
  122.     int function;
  123. } options_t;
  124.  
  125. void init_options(options_t *options)
  126. {
  127.     options->flags     = 0;
  128.     options->component_name = NULL;
  129.     options->m_component= NULL;
  130.     options->color = (pixel_t) { 0, 0, 0 };
  131.     options->input     = NULL;
  132.     options->output    = NULL;
  133.     options->function  = 0;
  134. }
  135.  
  136. void free_options(options_t *options)
  137. {
  138.     if (options->input)
  139.         free(options->input);
  140.  
  141.     if (options->output)
  142.         free(options->output);
  143. }
  144. ///////////////�������� ���� ����!!!
  145. void print_help()
  146. {
  147.     fputs(
  148.         "usage: cw [options]\n"
  149.         "function-like options:\n"
  150.         "  --help / -h - print help message\n"
  151.         "  --info / -i - print image info\n"
  152.         "  --rgbfilter / -R - set selected component to 0 or 255\n"
  153.         "  --component_name / -n - component that needs to be changed\n"
  154.         "  --max / -M - change the given component to 255\n"
  155.         "  --min / -m - change the given component to 0\n"
  156.         "  --fill / -F - fill the entire image with the specified color\n"
  157.         "  --color / -c RRR.GGG.BBB - image fill color\n"
  158.         "  --input FILENAME - input file\n"
  159.         "  --output FILENAME - output file\n", stdout
  160.     );
  161. }
  162.  
  163. int print_image_info(image_t *image)
  164. {
  165.     printf("width: %d\n", (int)image->info.width);
  166.     printf("height: %d\n", (int)image->info.height);
  167.     printf("planes: %d\n", (int)image->info.planes);
  168.     printf("bit_count: %d\n", (int)image->info.bit_count);
  169.     printf("compression: %d\n", (int)image->info.compression);
  170.     printf("image_size: %d\n", (int)image->info.image_size);
  171.     printf("x_pixels_per_meter: %d\n", (int)image->info.x_pixels_per_meter);
  172.     printf("y_pixels_per_meter: %d\n", (int)image->info.y_pixels_per_meter);
  173.     printf("colors_used: %d\n", (int)image->info.colors_used);
  174.     printf("colors_important: %d\n", (int)image->info.colors_important);
  175.  
  176.     return SUCCESS;
  177. }
  178.  
  179. int str2pixel(char *str, pixel_t *pixel)
  180. {
  181.     int r, g, b;
  182.     int n = sscanf(str, "%d.%d.%d", &r, &g, &b);
  183.  
  184.     if (n != 3) {
  185.         fprintf(stderr, "error: can`t read color\n");
  186.         return FAILURE;
  187.     }
  188.  
  189.     if (r < 0 || g < 0 || b < 0 || r > 255 || g > 255 | b > 255) {
  190.         fprintf(stderr, "error: invalid color range\n");
  191.         return FAILURE;
  192.     }
  193.  
  194.     pixel->r = r;
  195.     pixel->g = g;
  196.     pixel->b = b;
  197.  
  198.     return SUCCESS;
  199. }
  200. int do_option_rgbfilter(image_t *image, char *component_name, char *m_component){
  201.     int flag = 0;
  202.     if (strcmp(m_component, "max") == 0)
  203.         flag = 1;
  204.     for (int x = 0; x < image->info.width; x++) {
  205.         for (int y = 0; y < image->info.height; y++) {
  206.             pixel_t pixel = image->data[x + y * image->info.width];
  207.             if (flag) {
  208.                 if (strcmp(component_name, "red") == 0)
  209.                     pixel.r = 255;
  210.                 if (strcmp(component_name, "green") == 0)
  211.                     pixel.g = 255;
  212.                 if (strcmp(component_name, "blue") == 0)
  213.                     pixel.b = 255;
  214.             } else {
  215.                 if (strcmp(component_name, "red") == 0)
  216.                     pixel.r = 0;
  217.                 if (strcmp(component_name, "green") == 0)
  218.                     pixel.g = 0;
  219.                 if (strcmp(component_name, "blue") == 0)
  220.                     pixel.b = 0;
  221.             }
  222.         }
  223.     }
  224.     return SUCCESS;
  225. }
  226.  
  227. int do_option_fill(image_t *image, pixel_t color){
  228.     for (int x = 0; x < image->info.width; x++) {
  229.         for (int y = 0; y < image->info.height; y++) {
  230.             pixel_t pixel = image->data[x + y * image->info.width];
  231.             image->data[x + y * image->info.width] = color;
  232.         }
  233.     }
  234.     return SUCCESS;
  235. }
  236.  
  237. int save_bmp(image_t *image, char *filename)
  238. {
  239.     FILE *fp = fopen(filename, "wb");
  240.     if (fp == NULL) {
  241.         fprintf(stderr, "error: failed to open");
  242.         return FAILURE;
  243.     }
  244.  
  245.     bmp_header_t header = {
  246.         .signature = 0x4D42,
  247.         .reserved = 0,
  248.         .filesize = -1,
  249.         .data_offset = sizeof(bmp_header_t) + sizeof(bmp_infoheader_t)
  250.     };
  251.  
  252.     fwrite(&header, 1, sizeof(bmp_header_t), fp);
  253.     fwrite(&image->info, 1, sizeof(bmp_infoheader_t), fp);
  254.     fwrite(image->data, 1, sizeof(pixel_t) * image->info.width * image->info.height, fp);
  255.  
  256.     fseek(fp, 0, SEEK_END);
  257.     uint32_t filesize = ftell(fp);
  258.     fseek(fp, 2, SEEK_SET);
  259.     fwrite(&filesize, 1, 4, fp);
  260. ///??????
  261.     fclose(fp);
  262.     return SUCCESS;
  263. }
  264.  
  265. void free_image(image_t *image)
  266. {
  267.     free(image->data);
  268. }
  269.  
  270. int main(int argc, char **argv){
  271.  
  272.     puts("Course work for option 3.3, created by Fominykh Egor.");
  273.  
  274.     static_assert(sizeof(bmp_header_t) == 14, "incorrect header size");
  275.  
  276.     static_assert(sizeof(bmp_infoheader_t) == 40, "incorrect infoheader size");
  277.    
  278.     options_t options;
  279.     init_options(&options);
  280.  
  281.     int opt = getopt_long(argc, argv, "hiRFn:Mmc:", longopts, NULL);
  282.     while (opt != -1) {
  283.         if (opt == '?') {
  284.             fprintf(stderr, "error: invalid option\n");
  285.             exit(EXIT_CW_FAILURE);
  286.         }
  287.  
  288.         switch (opt) {
  289.             case 'h':
  290.                 print_help();
  291.                 free_options(&options);
  292.                 exit(EXIT_CW_OK);
  293.             case 'i':
  294.             case 'R':
  295.             case 'F':
  296.                 options.function = opt;
  297.                 break;
  298.             case 'n':
  299.                 options.component_name = optarg;
  300.                 options.flags |= OPTION_COMPONENT_NAME;
  301.                 break;
  302.             case 'M':
  303.                 options.m_component = "max";
  304.                 options.flags |= OPTION_FILTER;
  305.                 break;
  306.             case 'm':
  307.                 options.m_component = "min";
  308.                 options.flags |= OPTION_FILTER;
  309.                 break;
  310.             case 'c':
  311.                 if (str2pixel(optarg, &options.color) == FAILURE) {
  312.                     free_options(&options);
  313.                     exit(EXIT_CW_FAILURE);
  314.                 }
  315.                 options.flags |= OPTION_COLOR;
  316.                 break;
  317.             case '>':
  318.                 options.input = strdup(optarg);
  319.                 break;
  320.             case '<':
  321.                 options.output = strdup(optarg);
  322.                 break;
  323.         }
  324.  
  325.         opt = getopt_long(argc, argv, "hiRFn:Mmc:", longopts, NULL);
  326.     }
  327.  
  328.     if (options.output == NULL)
  329.         options.output = strdup("out.bmp");
  330.  
  331.     if (options.input == NULL && optind >= argc) {
  332.         fprintf(stderr, "error: no input file\n");
  333.         free_options(&options);
  334.         exit(EXIT_CW_FAILURE);
  335.     }
  336.  
  337.     if (options.input == NULL)
  338.         options.input = strdup(argv[optind]);
  339.  
  340.     if (options.function == 0) {
  341.         fprintf(stderr, "error: function not selected\n");
  342.         free_options(&options);
  343.         exit(EXIT_CW_FAILURE);
  344.     }
  345.  
  346.     image_t image;
  347.     int ret = load_bmp(&image, options.input);
  348.     if (ret == FAILURE) {
  349.         free_options(&options);
  350.         exit(EXIT_CW_FAILURE);
  351.     }
  352.  
  353.     switch (options.function) {
  354.         case 'i':
  355.             ret = print_image_info(&image);
  356.             break;
  357.         case 'R':
  358.             if ((options.flags & (OPTION_COMPONENT_NAME | OPTION_FILTER)) != (OPTION_COMPONENT_NAME | OPTION_FILTER)) {
  359.                 fprintf(stderr, "error: not enough arguments\n");
  360.                 ret = FAILURE;
  361.             }
  362.             else
  363.                 ret = do_option_rgbfilter(&image, options.component_name, options.m_component);
  364.             break;
  365.         case 'F':
  366.             if ((options.flags & OPTION_COLOR) != OPTION_COLOR) {
  367.                 fprintf(stderr, "error: not enough arguments\n");
  368.                 ret = FAILURE;
  369.             }
  370.             else
  371.                 ret = do_option_fill(&image, options.color);
  372.             break;
  373.     }
  374.  
  375.     if (ret == FAILURE) {
  376.         free_image(&image);
  377.         free_options(&options);
  378.         exit(EXIT_CW_FAILURE);
  379.     }
  380.  
  381.     if (options.function != 'i') {
  382.         ret = save_bmp(&image, options.output);
  383.         if (ret == FAILURE) {
  384.             exit(EXIT_CW_FAILURE);
  385.         }
  386.     }
  387.  
  388.     free_image(&image);
  389.     free_options(&options);
  390.     return EXIT_CW_OK;
  391. }
  392.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement