Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <assert.h>
- #include <string.h>
- #include <errno.h>
- #include <getopt.h>
- #define FAILURE -1
- #define SUCCESS 0
- #define EXIT_CW_FAILURE 40
- #define EXIT_CW_OK 0
- typedef struct bmp_header {
- uint16_t signature;
- uint32_t filesize;
- uint32_t reserved;
- uint32_t data_offset;
- } __attribute__((packed)) bmp_header_t;
- typedef struct info_header {
- uint32_t size;
- uint32_t width;
- uint32_t height;
- uint16_t planes;
- uint16_t bit_count;
- uint32_t compression;
- uint32_t image_size;
- uint32_t x_pixels_per_meter;
- uint32_t y_pixels_per_meter;
- uint32_t colors_used;
- uint32_t colors_important;
- } __attribute__((packed)) bmp_infoheader_t;
- typedef struct {
- uint8_t b, g, r;
- } pixel_t;
- typedef struct image {
- bmp_infoheader_t info;
- pixel_t *data;
- } image_t;
- //-------------------------------------------------------------------
- int load_bmp(image_t *image, const char *filename)
- {
- FILE *fp = fopen(filename, "rb");
- if (fp == NULL) {
- fprintf(stderr, "error: failed to open\n");
- return FAILURE;
- }
- bmp_header_t header;
- int n_read = fread(&header, 1, sizeof(header), fp);
- if (n_read != sizeof(bmp_header_t)) {
- fprintf(stderr, "error: failed to read bmp header\n");
- fclose(fp);
- return FAILURE;
- }
- n_read = fread(&image->info, 1, sizeof(bmp_infoheader_t), fp);
- if (n_read != sizeof(bmp_infoheader_t)) {
- fprintf(stderr, "error: failed to read bmp info header\n");
- fclose(fp);
- return FAILURE;
- }
- if (header.signature != 0x4D42) {
- fprintf(stderr, "error: invalid bmp signature\n");
- fclose(fp);
- return FAILURE;
- }
- if (image->info.bit_count != 24 || image->info.compression != 0) {
- fprintf(stderr, "error: unsupported bmp format\n");
- fclose(fp);
- return FAILURE;
- }
- fseek(fp, header.data_offset, SEEK_SET);
- image->data = (pixel_t*)malloc(sizeof(pixel_t) * image->info.width * image->info.height);
- if (image->data == NULL) {
- fprintf(stderr, "error: not enough memory");
- fclose(fp);
- return FAILURE;
- }
- fread(image->data, 1, sizeof(pixel_t) * image->info.width * image->info.height, fp);
- fclose(fp);
- return SUCCESS;
- }
- struct option longopts[] = {
- { "help", 0, NULL, 'h' },
- { "info", 0, NULL, 'i' },
- { "rgbfilter", 0, NULL, 'R' },
- { "fill", 0, NULL, 'F' },
- { "component_name", 1, NULL, 'n' },
- { "max", 0, NULL, 'M' },
- { "min", 0, NULL, 'm' },
- { "color", 1, NULL, 'c' },
- { "input", 1, NULL, '>' },
- { "output", 1, NULL, '<' },
- {NULL, 0, NULL, 0}
- };
- #define OPTION_COMPONENT_NAME 1
- #define OPTION_FILTER 2
- #define OPTION_COLOR 4
- typedef struct {
- int flags;
- char *component_name;
- char *m_component;
- pixel_t color;
- char *input;
- char *output;
- int function;
- } options_t;
- void init_options(options_t *options)
- {
- options->flags = 0;
- options->component_name = NULL;
- options->m_component= NULL;
- options->color = (pixel_t) { 0, 0, 0 };
- options->input = NULL;
- options->output = NULL;
- options->function = 0;
- }
- void free_options(options_t *options)
- {
- if (options->input)
- free(options->input);
- if (options->output)
- free(options->output);
- }
- ///////////////�������� ���� ����!!!
- void print_help()
- {
- fputs(
- "usage: cw [options]\n"
- "function-like options:\n"
- " --help / -h - print help message\n"
- " --info / -i - print image info\n"
- " --rgbfilter / -R - set selected component to 0 or 255\n"
- " --component_name / -n - component that needs to be changed\n"
- " --max / -M - change the given component to 255\n"
- " --min / -m - change the given component to 0\n"
- " --fill / -F - fill the entire image with the specified color\n"
- " --color / -c RRR.GGG.BBB - image fill color\n"
- " --input FILENAME - input file\n"
- " --output FILENAME - output file\n", stdout
- );
- }
- int print_image_info(image_t *image)
- {
- printf("width: %d\n", (int)image->info.width);
- printf("height: %d\n", (int)image->info.height);
- printf("planes: %d\n", (int)image->info.planes);
- printf("bit_count: %d\n", (int)image->info.bit_count);
- printf("compression: %d\n", (int)image->info.compression);
- printf("image_size: %d\n", (int)image->info.image_size);
- printf("x_pixels_per_meter: %d\n", (int)image->info.x_pixels_per_meter);
- printf("y_pixels_per_meter: %d\n", (int)image->info.y_pixels_per_meter);
- printf("colors_used: %d\n", (int)image->info.colors_used);
- printf("colors_important: %d\n", (int)image->info.colors_important);
- return SUCCESS;
- }
- int str2pixel(char *str, pixel_t *pixel)
- {
- int r, g, b;
- int n = sscanf(str, "%d.%d.%d", &r, &g, &b);
- if (n != 3) {
- fprintf(stderr, "error: can`t read color\n");
- return FAILURE;
- }
- if (r < 0 || g < 0 || b < 0 || r > 255 || g > 255 | b > 255) {
- fprintf(stderr, "error: invalid color range\n");
- return FAILURE;
- }
- pixel->r = r;
- pixel->g = g;
- pixel->b = b;
- return SUCCESS;
- }
- int do_option_rgbfilter(image_t *image, char *component_name, char *m_component){
- int flag = 0;
- if (strcmp(m_component, "max") == 0)
- flag = 1;
- for (int x = 0; x < image->info.width; x++) {
- for (int y = 0; y < image->info.height; y++) {
- pixel_t pixel = image->data[x + y * image->info.width];
- if (flag) {
- if (strcmp(component_name, "red") == 0)
- pixel.r = 255;
- if (strcmp(component_name, "green") == 0)
- pixel.g = 255;
- if (strcmp(component_name, "blue") == 0)
- pixel.b = 255;
- } else {
- if (strcmp(component_name, "red") == 0)
- pixel.r = 0;
- if (strcmp(component_name, "green") == 0)
- pixel.g = 0;
- if (strcmp(component_name, "blue") == 0)
- pixel.b = 0;
- }
- }
- }
- return SUCCESS;
- }
- int do_option_fill(image_t *image, pixel_t color){
- for (int x = 0; x < image->info.width; x++) {
- for (int y = 0; y < image->info.height; y++) {
- pixel_t pixel = image->data[x + y * image->info.width];
- image->data[x + y * image->info.width] = color;
- }
- }
- return SUCCESS;
- }
- int save_bmp(image_t *image, char *filename)
- {
- FILE *fp = fopen(filename, "wb");
- if (fp == NULL) {
- fprintf(stderr, "error: failed to open");
- return FAILURE;
- }
- bmp_header_t header = {
- .signature = 0x4D42,
- .reserved = 0,
- .filesize = -1,
- .data_offset = sizeof(bmp_header_t) + sizeof(bmp_infoheader_t)
- };
- fwrite(&header, 1, sizeof(bmp_header_t), fp);
- fwrite(&image->info, 1, sizeof(bmp_infoheader_t), fp);
- fwrite(image->data, 1, sizeof(pixel_t) * image->info.width * image->info.height, fp);
- fseek(fp, 0, SEEK_END);
- uint32_t filesize = ftell(fp);
- fseek(fp, 2, SEEK_SET);
- fwrite(&filesize, 1, 4, fp);
- ///??????
- fclose(fp);
- return SUCCESS;
- }
- void free_image(image_t *image)
- {
- free(image->data);
- }
- int main(int argc, char **argv){
- puts("Course work for option 3.3, created by Fominykh Egor.");
- static_assert(sizeof(bmp_header_t) == 14, "incorrect header size");
- static_assert(sizeof(bmp_infoheader_t) == 40, "incorrect infoheader size");
- options_t options;
- init_options(&options);
- int opt = getopt_long(argc, argv, "hiRFn:Mmc:", longopts, NULL);
- while (opt != -1) {
- if (opt == '?') {
- fprintf(stderr, "error: invalid option\n");
- exit(EXIT_CW_FAILURE);
- }
- switch (opt) {
- case 'h':
- print_help();
- free_options(&options);
- exit(EXIT_CW_OK);
- case 'i':
- case 'R':
- case 'F':
- options.function = opt;
- break;
- case 'n':
- options.component_name = optarg;
- options.flags |= OPTION_COMPONENT_NAME;
- break;
- case 'M':
- options.m_component = "max";
- options.flags |= OPTION_FILTER;
- break;
- case 'm':
- options.m_component = "min";
- options.flags |= OPTION_FILTER;
- break;
- case 'c':
- if (str2pixel(optarg, &options.color) == FAILURE) {
- free_options(&options);
- exit(EXIT_CW_FAILURE);
- }
- options.flags |= OPTION_COLOR;
- break;
- case '>':
- options.input = strdup(optarg);
- break;
- case '<':
- options.output = strdup(optarg);
- break;
- }
- opt = getopt_long(argc, argv, "hiRFn:Mmc:", longopts, NULL);
- }
- if (options.output == NULL)
- options.output = strdup("out.bmp");
- if (options.input == NULL && optind >= argc) {
- fprintf(stderr, "error: no input file\n");
- free_options(&options);
- exit(EXIT_CW_FAILURE);
- }
- if (options.input == NULL)
- options.input = strdup(argv[optind]);
- if (options.function == 0) {
- fprintf(stderr, "error: function not selected\n");
- free_options(&options);
- exit(EXIT_CW_FAILURE);
- }
- image_t image;
- int ret = load_bmp(&image, options.input);
- if (ret == FAILURE) {
- free_options(&options);
- exit(EXIT_CW_FAILURE);
- }
- switch (options.function) {
- case 'i':
- ret = print_image_info(&image);
- break;
- case 'R':
- if ((options.flags & (OPTION_COMPONENT_NAME | OPTION_FILTER)) != (OPTION_COMPONENT_NAME | OPTION_FILTER)) {
- fprintf(stderr, "error: not enough arguments\n");
- ret = FAILURE;
- }
- else
- ret = do_option_rgbfilter(&image, options.component_name, options.m_component);
- break;
- case 'F':
- if ((options.flags & OPTION_COLOR) != OPTION_COLOR) {
- fprintf(stderr, "error: not enough arguments\n");
- ret = FAILURE;
- }
- else
- ret = do_option_fill(&image, options.color);
- break;
- }
- if (ret == FAILURE) {
- free_image(&image);
- free_options(&options);
- exit(EXIT_CW_FAILURE);
- }
- if (options.function != 'i') {
- ret = save_bmp(&image, options.output);
- if (ret == FAILURE) {
- exit(EXIT_CW_FAILURE);
- }
- }
- free_image(&image);
- free_options(&options);
- return EXIT_CW_OK;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement