Добавил:
baraevaliza
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабы и курсачи 2022-2023 / 2 сем / Baraeva_Elizaveta_cw
.pdf
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 сем
