Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы и курсачи 2022-2023 / 2 сем / Baraeva_Elizaveta_cw

.pdf
Скачиваний:
0
Добавлен:
09.09.2026
Размер:
1 Мб
Скачать
21
fprintf(stderr, "Неправильный ввод числа\n"); return; } sum++; break; case 'i': if(optarg == NULL){ fprintf(stderr, "Неправильный ввод имени файла\n"); return; } file_name = optarg; sum++; break; default: fprintf(stderr, "Неправильный ввод флага\n"); return; } } if(sum != 2 || file_name == NULL || color == '0'){ fprintf(stderr, "Введено неправильное количество аргументов\n"); return; } PNG image; if(read_png(file_name, &image)){ filter(&image, color, value); write_png(file_name, &image); } }
void case_circle(int argc, char* argv[]){ opterr = 0; const char* short_options = ""; const struct option long_options[] = { {"start", required_argument, NULL, 't'}, {"end", required_argument, NULL, 'e'}, {"centre", required_argument, NULL, 'x'}, {"radius", required_argument, NULL, 'a'}, {"width", required_argument, NULL, 'w'}, {"color", required_argument, NULL, 'o'}, {"fill", required_argument, NULL, 'l'}, {"file", required_argument, NULL, 'i'}, {NULL, 0, NULL, 0}}; int rez, option_index, w = -1, r = -1, start[2] = {-1, -1}, end[2] = {-1, -1}, center[2] = {-1, -1}, color[3] = {-1, -1, -1}, fill[3] = {-1, ­1, -1}, sum = 0; char *file_name = NULL; bool bool_start = false, bool_end = false, bool_center = false, bool_color = false, bool_fill = false; while((rez = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1){ switch(rez){ case 't': if(!(scan_coordinates(optarg, start))){ fprintf(stderr, "Неправильный ввод координат\n"); return; } bool_start = true;
22
sum++; break; case 'e': if(!(scan_coordinates(optarg, end))){ fprintf(stderr, "Неправильный ввод координат\n"); return; } bool_end = true; sum++; break; case 'x': if(!(scan_coordinates(optarg, center))){ fprintf(stderr, "Неправильный ввод координат\n"); return; } bool_center = true; sum++; break; case 'a': if(!(scan_number(optarg, &r))){ fprintf(stderr, "Неправильный ввод числа\n"); return; } sum++; break; case 'w': if(!(scan_number(optarg, &w))){ fprintf(stderr, "Неправильный ввод числа\n"); return; } sum++; break; case 'o': if(!(scan_color(optarg, color))){ fprintf(stderr, "Неправильный ввод цвета\n"); return; } bool_color = true; sum++; break; case 'l': if(!(scan_color(optarg, fill))){ fprintf(stderr, "Неправильный ввод цвета\n"); return; } bool_fill = true; sum++; break; case 'i': if(optarg == NULL){ fprintf(stderr, "Неправильный ввод имени файла\n"); return; } file_name = optarg; sum++; break; default:
23
fprintf(stderr, "Неправильный ввод флага\n"); return; } } if(!(file_name != NULL && w != -1 && bool_color == true && (bool_start == true && bool_end == true && (sum == 5 || sum == 6 && bool_fill == true) || bool_center == true && r != -1 && (sum == 5 || sum == 6 && bool_fill == true)))){ fprintf(stderr, "Введено неправильное количество аргументов\n"); return; } PNG image; if(read_png(file_name, &image)){ circle(&image, start, end, center, r, w, color, fill); write_png(file_name, &image); } }
void case_split(int argc, char* argv[]){ opterr = 0; const char* short_options = "n:m:"; const struct option long_options[] = { {"width", required_argument, NULL, 'w'}, {"color", required_argument, NULL, 'o'}, {"file", required_argument, NULL, 'i'}, {NULL, 0, NULL, 0}}; int rez, option_index, n = -1, m = -1, w = -1, color[3] = {-1, -1, ­1}, sum = 0; char *file_name = NULL; bool bool_color = false; while((rez = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1){ switch(rez){ case 'n': if(!(scan_number(optarg, &n))){ fprintf(stderr, "Неправильный ввод числа\n"); return; } sum++; break; case 'm': if(!(scan_number(optarg, &m))){ fprintf(stderr, "Неправильный ввод числа\n"); return; } sum++; break; case 'w': if(!(scan_number(optarg, &w))){ fprintf(stderr, "Неправильный ввод числа\n"); return; } sum++; break; case 'o': if(!(scan_color(optarg, color))){
24
fprintf(stderr, "Неправильный ввод числа\n"); return; } bool_color = true; sum++; break; case 'i': if(optarg == NULL){ fprintf(stderr, "Неправильный ввод имени файла\n"); return; } file_name = optarg; sum++; break; default: fprintf(stderr, "Неправильный ввод флага\n"); return; } } if(sum != 5 || file_name == NULL || n == -1 || m == -1 || w == -1 || bool_color == false){ fprintf(stderr, "Введено неправильное количество аргументов\n"); return; } PNG image; if(read_png(file_name, &image)){ split(&image, n, m, w, color); write_png(file_name, &image); } }
void help(){ puts("Руководство по использованию программы:"); puts("Программа обрабатывает PNG-файлы c глубиной изображения 24 бита на пиксель\n");
puts("Обозначения:"); puts("\t x,y - целые, неотрицательный числа"); puts("\t a - целое, положительное число"); puts("\t c - число равное либо 0, либо 255"); puts("\tr,g,b - целые числа в диапозоне [0,255]\n");
puts("Функции/флаги:"); puts("-c/--circle -- рисование окружности"); puts("\t--start x,y - координаты левого верхнего квадрата, в который будет вписана окружность"); puts("\t--end x,y - координаты правого нижнего квадрата, в который будет вписана окружность"); puts("\tили"); puts("\t--centre x,y - координаты центра окружности"); puts("\t--radius a - радиус окружности\n");
puts("\t--width a - значение толщины окружности"); puts("\t--color r,g,b - значения цветов окружности"); puts("\t--fill r,g,b - значения цветов заливки окружности (данный флаг может отсутствовать)"); puts("\t--file <путь> - файл для записи изображения\n");
25
puts("-f/--filter -- наложение фильтра на изображение"); puts("\t-r c - значение цвета, устанавливаемое в красный цвет"); puts("\t-g c - значение цвета, устанавливаемое в зеленый цвет"); puts("\t-b c - значение цвета, устанавливаемое в синий цвет"); puts("\t--file <путь> - файл для записи изображения\n");
puts("-s/--split -- разделение изображения на N*M частей"); puts("\t-n a - количество частей по оси Y"); puts("\t-m a - количество частей по оси X"); puts("\t--width a - значение толищны линии"); puts("\t--color r,g,b - значения цветов линии"); puts("\t--file <путь> - файл для записи изображения\n");
puts("-h/--help - вывод справки о программе"); puts("-i/--info <путь> - вывод информации о PNG-файле"); }
void info(char* file_name){ PNG image; if(read_png(file_name, &image)){ puts("Информация о файле:"); printf("Ширина изображения: %d\n", image.width); printf("Высота изображения: %d\n", image.height); printf("Тип цвета: %d\n", image.color_type); printf("Глубина цвета: %d\n", image.bit_depth); } write_png(file_name, &image); }
int main(int argc, char *argv[]){ opterr = 0; const char* short_options = "hi:cfs"; const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"info", required_argument, NULL, 'i'}, {"circle", no_argument, NULL, 'c'}, {"filter", no_argument, NULL, 'f'}, {"split", no_argument, NULL, 's'}, {NULL, 0, NULL, 0}}; int rez, option_index; rez = getopt_long(argc, argv, short_options, long_options, &option_index); switch(rez){ case 'h': help(); break; case 'i': info(optarg); break; case 'c': case_circle(argc, argv); break; case 'f': case_filter(argc, argv); break; case 's':
26
case_split(argc, argv); break; default: fprintf(stderr, "Неправильный ввод флага\n"); help(); } return 0; }
void put_pixel(PNG *image, int x, int y, int* color){ image->row_pointers[y][x * 3] = color[0]; image->row_pointers[y][x * 3 + 1] = color[1]; image->row_pointers[y][x * 3 + 2] = color[2]; }
void draw_vertical_line(PNG *image, int x, int* color){ if(x < 0 || x > image->width) return; for(int y = 0; y < image->height; y++){ put_pixel(image, x, y, color); } }
void draw_horizontal_line(PNG *image, int y, int* color){ if(y < 0 || y > image->height) return; for(int x = 0; x < image->width; x++){ put_pixel(image, x, y, color); } }
void xLine(PNG* image, int x1, int x2, int y, int* color){ while(x1 <= x2){ if(x1 >= 0 && x1 < image->width && y >= 0 && y < image->height) put_pixel(image, x1, y, color); x1++; } }
void yLine(PNG* image, int x, int y1, int y2, int* color){ while(y1 <= y2){ if(y1 >= 0 && y1 < image->height && x >= 0 && x < image->width) put_pixel(image, x, y1, color); y1++; } }
void fill_circle(PNG* image, int x, int y, int* color, int* fill){ if(0 <= y && y < image->height && 0 <= x && x < image->width && !(image->row_pointers[y][x * 3] == fill[0] && image­>row_pointers[y][x * 3 + 1] == fill[1] && image->row_pointers[y][x * 3 + 2] == fill[2]) && !(image->row_pointers[y][x * 3] == color[0] && image­>row_pointers[y][x * 3 + 1] == color[1] && image->row_pointers[y][x * 3 + 2] == color[2])){ put_pixel(image, x, y, fill); fill_circle(image, x + 1, y, color, fill);
27
fill_circle(image, x, y + 1, color, fill); fill_circle(image, x - 1, y, color, fill); fill_circle(image, x, y - 1, color, fill); } }
void circle_part(PNG* image, int x0, int y0, int r, int w, int* color, int part){ int out, in, y = 0; if(w % 2){ out = r + w / 2; in = r - w / 2; } else{ out = r + w / 2; in = r - w / 2 + 1; } int erro = 1 - out, erri = 1 - in; while(out >= y){ switch(part){ case 1: xLine(image, x0 + in, x0 + out, y0 - y, color); yLine(image, x0 + y, y0 - out, y0 - in, color); break; case 2: xLine(image, x0 - out, x0 - in, y0 - y, color); yLine(image, x0 - y, y0 - out, y0 - in, color); break; case 3: xLine(image, x0 - out, x0 - in, y0 + y, color); yLine(image, x0 - y, y0 + in, y0 + out, color); break; case 4: xLine(image, x0 + in, x0 + out, y0 + y, color); yLine(image, x0 + y, y0 + in, y0 + out, color); } y++; if(erro < 0) erro += 2 * y + 1; else{ out--; erro += 2 * (y - out + 1); } if(y > r - w / 2) in = y; else{ if(erri < 0) erri += 2 * y + 1; else{ in--; erri += 2 * (y - in + 1); } } } }
28
void circle(PNG* image, int* start, int* end, int* center, int r, int w, int* color, int* fill){ int R = -1; if(center[0] == -1 && center[1] == -1 && r == -1){ if(end[0] < start[0] || end[1] < start[1]){ fprintf(stderr, "Неправильный ввод координат\n"); return; } if((end[0] - start[0]) != (end[1] - start[1])){ fprintf(stderr, "Неправильный ввод координат, не квадрат\n"); return; } if((end[0] - start[0]) % 2){ int r = (end[0] - start[0]) / 2; int x0 = start[0] + r, y0 = start[1] + r; circle_part(image, x0, y0, r, w, color, 2); circle_part(image, x0 + 1, y0, r, w, color, 1); circle_part(image, x0, y0 + 1, r, w, color, 3); circle_part(image, x0 + 1, y0 + 1, r, w, color, 4); if(fill[0] != -1 && fill[1] != -1 && fill[2] != -1){ fill_circle(image, x0, y0, color, fill); } return; } R = (end[0] - start[0]) / 2; center[0] = start[0] + R; center[1] = start[1] + R; } if(R != -1) r = R; int out, in, y = 0; if(w % 2){ out = r + w / 2; in = r - w / 2; } else{ out = r + w / 2; in = r - w / 2 + 1; } int erro = 1 - out, erri = 1 - in; while(out >= y){ xLine(image, center[0] + in, center[0] + out, center[1] + y, color); yLine(image, center[0] + y, center[1] + in, center[1] + out, color); xLine(image, center[0] - out, center[0] - in, center[1] + y, color); yLine(image, center[0] - y, center[1] + in, center[1] + out, color); xLine(image, center[0] - out, center[0] - in, center[1] - y, color); yLine(image, center[0] - y, center[1] - out, center[1] - in, color); xLine(image, center[0] + in, center[0] + out, center[1] - y, color); yLine(image, center[0] + y, center[1] - out, center[1] - in, color);
29
y++; if(erro < 0) erro += 2 * y + 1; else{ out--; erro += 2 * (y - out + 1); } if(y > r - w / 2) in = y; else{ if(erri < 0) erri += 2 * y + 1; else{ in--; erri += 2 * (y - in + 1); } } } if(fill[0] != -1 && fill[1] != -1 && fill[2] != -1){ fill_circle(image, center[0], center[1], color, fill); } }
void split(PNG *image, int N, int M, int W, int* color){ if(N > image->height || M > image->width){ fprintf(stderr, "Неправильный ввод числа\n"); return; } float len = (float) (image->width - (M - 1)) / M; float x = len; while(x < image->width){ for(int i = x - W / 2; i < x - W / 2 + W; i++){ draw_vertical_line(image, i, color); } x += len + 1; } len = (float) (image->height - (N - 1)) / N; float y = len; while(y < image->height){ for(int i = y - W / 2; i < y - W / 2 + W; i++){ draw_horizontal_line(image, i, color); } y += len + 1; } }
void filter(PNG *image, char color, int value){ switch (color){ case 'r': for(int y = 0; y < image->height; y++){ png_byte *row = image->row_pointers[y]; for(int x = 0; x < image->width * 3; x += 3){ row[x] = value; } } break; case 'g':
30
for(int y = 0; y < image->height; y++){ png_byte *row = image->row_pointers[y]; for(int x = 1; x < image->width * 3; x += 3){ row[x] = value; } } break; case 'b': for(int y = 0; y < image->height; y++){ png_byte *row = image->row_pointers[y]; for(int x = 2; x < image->width * 3; x += 3){ row[x] = value; } } } }
bool read_png(char *file_name, PNG *image){ char header[8]; FILE *fp = fopen(file_name, "rb"); if(!fp){ fprintf(stderr, "Ошибка в открытии файла\n"); return false; } fread(header, sizeof(char), 8, fp); image->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!image->png_ptr){ fprintf(stderr, "Ошибка в png_create_read_struct\n"); return false; } image->info_ptr = png_create_info_struct(image->png_ptr); if (!image->info_ptr){ fprintf(stderr, "Ошибка в png_create_info_struct failed\n"); return false; } if(setjmp(png_jmpbuf(image->png_ptr))){ fprintf(stderr, "Ошибка во время init_io\n"); return false; } png_init_io(image->png_ptr, fp); png_set_sig_bytes(image->png_ptr, 8); png_read_info(image->png_ptr, image->info_ptr); image->width = png_get_image_width(image->png_ptr, image->info_ptr); image->height = png_get_image_height(image->png_ptr, image­>info_ptr); image->color_type = png_get_color_type(image->png_ptr, image­>info_ptr); image->bit_depth = png_get_bit_depth(image->png_ptr, image­>info_ptr); image->number_of_passes = png_set_interlace_handling(image->png_ptr); png_read_update_info(image->png_ptr, image->info_ptr); if (setjmp(png_jmpbuf(image->png_ptr))){ fprintf(stderr, "Ошибка во время read_image\n"); return false; }
Соседние файлы в папке 2 сем