Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <unistd.h>
- #include <cstdlib>
- #include <cstdio>
- #include <cstdarg>
- #include <getopt.h>
- #include <cstring>
- #include <cctype>
- #include <algorithm>
- #include <cmath>
- #include <string>
- using namespace std;
- #define PNG_DEBUG 3
- #include <png.h>
- struct Png{
- int width, height;
- png_byte color_type;
- png_byte bit_depth;
- png_structp png_ptr;
- png_infop info_ptr;
- int number_of_passes;
- png_bytep *row_pointers;
- };
- struct args{
- int start[2];
- int end[2];
- int nevv[2];
- int origin[4];
- int chosen[4];
- int width;
- int type;
- };
- void read_png_file(char *file_name, struct Png *image) {
- int x,y;
- unsigned char header[8]; // 8 is the maximum size that can be checked
- /* open file and test for it being a png */
- FILE *fp = fopen(file_name, "rb");
- if (!fp){
- // Some error handling: file could not be opened
- }
- fread(header, 1, 8, fp);
- if (png_sig_cmp(header, 0, 8)){
- // Some error handling: file is not recognized as a PNG
- }
- /* initialize stuff */
- image->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!image->png_ptr){
- // Some error handling: png_create_read_struct failed
- }
- image->info_ptr = png_create_info_struct(image->png_ptr);
- if (!image->info_ptr){
- // Some error handling: png_create_info_struct failed
- }
- if (setjmp(png_jmpbuf(image->png_ptr))){
- // Some error handling: error during init_io
- //png_destroy_read_struct(image->png_ptr, image->info_ptr,
- // (png_infopp) NULL);
- //fclose(fp);
- //return ERROR;
- }
- 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);
- /* read file */
- if (setjmp(png_jmpbuf(image->png_ptr))){
- // Some error handling: error during read_image
- }
- image->row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * image->height);
- for (y = 0; y < image->height; y++)
- image->row_pointers[y] = (png_byte *) malloc(png_get_rowbytes(image->png_ptr, image->info_ptr));
- png_read_image(image->png_ptr, image->row_pointers);
- fclose(fp);
- }
- void write_png_file(char *file_name, struct Png *image) {
- int x,y;
- /* create file */
- FILE *fp = fopen(file_name, "wb");
- if (!fp){
- // Some error handling: file could not be opened
- }
- /* initialize stuff */
- image->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!image->png_ptr){
- // Some error handling: png_create_write_struct failed
- }
- image->info_ptr = png_create_info_struct(image->png_ptr);
- if (!image->info_ptr){
- // Some error handling: png_create_info_struct failed
- }
- if (setjmp(png_jmpbuf(image->png_ptr))){
- // Some error handling: error during init_io
- }
- png_init_io(image->png_ptr, fp);
- /* write header */
- if (setjmp(png_jmpbuf(image->png_ptr))){
- // Some error handling: error during writing header
- }
- png_set_IHDR(image->png_ptr, image->info_ptr, image->width, image->height,
- image->bit_depth, image->color_type, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- png_write_info(image->png_ptr, image->info_ptr);
- /* write bytes */
- if (setjmp(png_jmpbuf(image->png_ptr))){
- // Some error handling: error during writing bytes
- }
- png_write_image(image->png_ptr, image->row_pointers);
- /* end write */
- if (setjmp(png_jmpbuf(image->png_ptr))){
- // Some error handling: error during end of write
- }
- png_write_end(image->png_ptr, NULL);
- /* cleanup heap allocation */
- for (y = 0; y < image->height; y++)
- free(image->row_pointers[y]);
- free(image->row_pointers);
- fclose(fp);
- }
- void printHelp()
- {
- printf("Справка\n");
- printf("--copy(-c) - делает копию заданного участка. Участок задается при помощи -S и -E области-источника и -N области-назначения.\n");
- printf("(Пример) --copy -S 100 200 -E 500 600 -N 0 0 fileOut.png");
- printf("--swap_color(-s) - Заменяет все пиксели одного заданного цвета на другой цвет. Цвет задается в формате RGB. -O(буква) для исходного цвета и (-C) для нового.\n");
- printf("(Пример) --swap_color -O 125 10 30 -C 200 162 3 fileOut.png\n");
- printf("--frame(-f) - Делает рамку в виде узора. Цвет задается при помощи -C, а ширина узора - -W, а тип рамки при помощи -T. \n");
- printf("(Пример) --frame -C 124 32 0 -W 30 -T 2 fileOut.png\n");
- printf("--highlight_rect(-h) - Поиск всех залитых прямоугольников заданного цвета. Задается цвет прямоугольников -O, цвет обводки -C, толщина линии -W.\n");
- printf("(Пример) --highlight_rect -R 100 156 200 -F 0 0 0 -W 5 fileOut.png\n");
- printf("--start(-S) - считывет координаты *целый числа* верхнего левого угла прямоугольной области (-С 32 23)\n");
- printf("--end(-E) - считывет координаты *целый числа* нижнего правого угла прямоугольной области (-E 32 23)\n");
- printf("--new(-N) - считывет координаты *целый числа* верхнего левого угла области-назначения (-N 0 0)\n");
- printf("--origin(-O) - считывет исходный цвет в формате RGB (-O 125 25 86)\n");
- printf("--chosen(-C) - считывет выбранный цвет в формате RGB (-C 0 25 86)\n");
- printf("--width(-W) - считывает значение ширины в пикселях (-W 10)\n");
- printf("--type(-T) - считывает тип рамки (всего возможно 3 типа). По умолчанию стоит рамка с типом 1.\n");
- printf("--info(-i) - выводит информацию о входном файле\n");
- printf("Строка команд должна заканчиваться названием файла вывода\n");
- }
- int isNumber(char *n)
- {
- for(int i = 0; i < strlen(n); i++)
- if(!isdigit(n[i]))
- return 0;
- return 1;
- }
- void swap_colors(struct Png *image, int orr, int og, int ob, int cr, int cg, int cb) {
- int x,y;
- if (png_get_color_type(image->png_ptr, image->info_ptr) == PNG_COLOR_TYPE_RGB){
- // Some error handling: input file is PNG_COLOR_TYPE_RGB but must be PNG_COLOR_TYPE_RGBA
- }
- if (png_get_color_type(image->png_ptr, image->info_ptr) != PNG_COLOR_TYPE_RGBA){
- // Some error handling: color_type of input file must be PNG_COLOR_TYPE_RGBA
- }
- for (y = 0; y < image->height; y++) {
- png_byte *row = image->row_pointers[y];
- for (x = 0; x < image->width; x++) {
- png_byte *ptr = &(row[x * 4]);
- if ((int) ptr[0] == orr && (int) ptr[1] == og && (int) ptr[2] == ob) {
- ptr[0] = static_cast<png_byte>(cr);
- ptr[1] = static_cast<png_byte>(cg);
- ptr[2] = static_cast<png_byte>(cb);
- }
- }
- }
- }
- void putPixel(png_byte *cur_row, int x, int y, int r, int g, int b, int a = 255) {
- png_byte *ptr = &(cur_row[(x*4)]);
- ptr[0] = static_cast<png_byte>(r);
- ptr[1] = static_cast<png_byte>(g);
- ptr[2] = static_cast<png_byte>(b);
- ptr[3] = static_cast<png_byte>(a);
- }
- void copyAndPaste(struct Png *image, int Sx, int Sy, int Fx, int Fy, int Nx, int Ny)
- {
- int x, y;
- int lenX = Fx - Sx + 1;
- int lenY = Fy - Sy + 1;
- png_bytep *new_row_pointers =(png_bytep *) malloc(sizeof(png_bytep) * lenY);
- for(y = 0; y < lenY; y++)
- {
- new_row_pointers[y] = (png_byte *)malloc(sizeof(png_byte)*4 * lenX);
- png_byte *new_row = new_row_pointers[y];
- png_byte *cur_row = image->row_pointers[Sy + y];
- for (x = 0; x < lenX; x++)
- {
- png_byte *ptr = &(cur_row[((Sx+x)*4)]);
- putPixel(new_row, x, y, ptr[0], ptr[1], ptr[2], ptr[3]);
- }
- }
- int maxX, maxY;
- lenX + Nx - 1> image -> width ? maxX = image -> width : maxX = lenX + Nx - 1;
- lenY + Ny - 1> image -> height ? maxY = image -> height : maxY = lenY + Ny - 1;
- for(y = Ny; y < maxY; y++) {
- png_byte *new_row = new_row_pointers[y - Ny];
- png_byte *ch_row = image->row_pointers[y];
- for (x = Nx; x < maxX; x++)
- {
- png_byte *toptr = &(new_row[(x - Nx)*4]);
- putPixel(ch_row, x, y, toptr[0], toptr[1], toptr[2], toptr[3]);
- }
- }
- for (y = 0; y < lenY; y++)
- free(new_row_pointers[y]);
- free(new_row_pointers);
- }
- void drawLine(struct Png *image, int x1, int y1, int x2, int y2, int r, int g, int b) {
- const int deltaX = abs(x2 - x1);
- const int deltaY = abs(y2 - y1);
- const int signX = x1 < x2 ? 1 : -1;
- const int signY = y1 < y2 ? 1 : -1;
- int error = deltaX - deltaY;
- if (x2 >= 0 && x2 < image -> width && y2 >= 0 && y2 < image -> height)
- putPixel(image -> row_pointers[y2], x2, y2, r, g, b);
- while(x1 != x2 || y1 != y2)
- {
- if (x1 >= 0 && x1 < image -> width && y1 >= 0 && y1 < image -> height)
- putPixel(image -> row_pointers[y1], x1, y1, r, g, b);
- const int error2 = error * 2;
- if(error2 > -deltaY)
- {
- error -= deltaY;
- x1 += signX;
- }
- if(error2 < deltaX)
- {
- error += deltaX;
- y1 += signY;
- }
- }
- }
- void drawCircle(struct Png *image, int xc, int yc, int inner, int outer, int R, int G, int B)
- {
- int xo = outer;
- int xi = inner;
- int y = 0;
- int erro = 1 - xo;
- int erri = 1 - xi;
- while(xo >= y) {
- drawLine(image, xc + xi, yc + y, xc + xo, yc + y, R, G, B);
- drawLine(image, xc + y, yc + xi, xc + y, yc + xo, R, G, B);
- drawLine(image, xc - xo, yc + y, xc - xi, yc + y, R, G, B);
- drawLine(image, xc - y, yc + xi, xc - y, yc + xo, R, G, B);
- drawLine(image, xc - xo, yc - y, xc - xi, yc - y, R, G, B);
- drawLine(image, xc - y, yc - xo, xc - y, yc - xi, R, G, B);
- drawLine(image, xc + xi, yc - y, xc + xo, yc - y, R, G, B);
- drawLine(image, xc + y, yc - xo, xc + y, yc - xi, R, G, B);
- y++;
- if (erro < 0) {
- erro += 2 * y + 1;
- } else {
- xo--;
- erro += 2 * (y - xo + 1);
- }
- if (y > inner) {
- xi = y;
- } else {
- if (erri < 0) {
- erri += 2 * y + 1;
- } else {
- xi--;
- erri += 2 * (y - xi + 1);
- }
- }
- }
- }
- void frameType1(struct Png *image, int width, int R, int G, int B) {
- for (int y = image -> height - width;;y -= width) {
- for (int j = y; j >= max(0, y - width); j--) {
- drawLine(image, 0, j, image -> width -1 - j, image -> height - 1, 255 - R, 255 - G, 255 - B);
- }
- y -= width;
- if (y < 0)
- break;
- }
- int ty = image -> height - 1;
- for (int j = ty; j >= max(0, ty - width + (image -> width % width)); j--) {
- drawLine(image, image -> width - 1, j, image -> width -1 - j, 0, 255 - R, 255 - G, 255 - B);
- }
- ty -= width + (image -> width % width);
- for (int y = ty;;y -= width) {
- for (int j = y; j >= max(0, y - width); j--) {
- drawLine(image, image -> width - 1, j, image -> width -1 - j, 0, 255 - R, 255 - G, 255 - B);
- }
- y -= width;
- if (y < 0)
- break;
- }
- }
- void frameType2(struct Png *image, int width, int R, int G, int B) {
- for (int y = 0;; y += width / 2) {
- for (int x = 0;; x += width / 2) {
- drawCircle(image, x, y, width / 2 - width / 20, width / 2, 255 - R, 255 - G, 255 - B);
- if (x >= image -> width)
- break;
- }
- if (y >= image -> height)
- break;
- }
- }
- void frameType3(struct Png *image, int width, int R, int G, int B) {
- for (int y = 0;; y += width / 2) {
- for (int x = 0;; x += width / 2) {
- drawCircle(image, x, y, width / 2 - width / 20, width / 2, 255 - R, 255 - G, 255 - B);
- if (x >= image -> width)
- break;
- }
- if (y >= image -> height)
- break;
- }
- }
- void drawFrame(struct Png *image, int R, int G, int B, int width, int type) {
- int wid = image -> width;
- int hei = image -> height;
- png_bytep *new_row_pointers =(png_bytep *) malloc(sizeof(png_bytep) * hei);
- for(int y = 0; y < hei; y++)
- {
- new_row_pointers[y] = (png_byte *)malloc(sizeof(png_byte)*4 * wid);
- png_byte *new_row = new_row_pointers[y];
- png_byte *cur_row = image->row_pointers[y];
- for (int x = 0; x < wid; x++)
- {
- png_byte *ptr = &(cur_row[(x*4)]);
- putPixel(new_row, x, y, ptr[0], ptr[1], ptr[2], ptr[3]);
- }
- }
- int lenX = image -> width + 2 * width;
- int lenY = image -> height + 2 * width;
- image ->row_pointers = (png_bytep *) realloc(image -> row_pointers, lenY * sizeof(png_bytep));
- for (int i = 0; i < lenY; i++) {
- image->row_pointers[i] = (png_byte *) realloc(image->row_pointers[i], sizeof(png_byte)*4 * lenX);
- }
- image -> width = lenX;
- image -> height = lenY;
- for (int i = 0; i < image -> height; i++) {
- png_byte *cur_row = image->row_pointers[i];
- for (int j = 0; j < image -> width; j++) {
- putPixel(cur_row, j, i, R, G, B, 255);
- }
- }
- switch (type) {
- case 1:
- frameType1(image, width, R, G, B);
- break;
- case 2:
- frameType2(image, width, R, G, B);
- break;
- case 3:
- frameType3(image, width, R, G, B);
- break;
- }
- for(int y = 0; y < hei; y++) {
- png_byte *new_row = new_row_pointers[y];
- png_byte *ch_row = image->row_pointers[width + y];
- for (int x = 0; x < wid; x++)
- {
- png_byte *toptr = &(new_row[x*4]);
- putPixel(ch_row, width + x, y, toptr[0], toptr[1], toptr[2], toptr[3]);
- }
- }
- for (int y = 0; y < hei; y++)
- free(new_row_pointers[y]);
- free(new_row_pointers);
- }
- int main(int argc, char **argv) {
- struct Png image;
- struct args arg;
- int longIndex = 0;
- int opt = 0;
- int flag = 0;
- read_png_file(argv[1], &image);
- arg.end[0] = -1;
- arg.end[1] = -1;
- arg.start[0] = -1;
- arg.start[1] = -1;
- arg.width = -1;
- arg.origin[0] = -1;
- arg.origin[1] = -1;
- arg.origin[2] = -1;
- arg.origin[3] = -1;
- arg.chosen[0] = -1;
- arg.chosen[1] = -1;
- arg.chosen[2] = -1;
- arg.chosen[3] = -1;
- arg.type = 1;
- char optstring[22] = "csfhS:E:N:O:C:W:T:in";
- struct option longOpts[] = {
- {"swap_color", no_argument, &flag, 's'},
- {"copy", no_argument, &flag, 'c'},
- {"frame", no_argument, &flag, 'f'},
- {"highlight_rect", no_argument, &flag, 'h'},
- {"note", required_argument, &flag, 'n'},
- {"start", required_argument, NULL, 'S'},
- {"end", required_argument, NULL, 'E'},
- {"new", required_argument, NULL, 'N'},
- {"origin", required_argument, NULL, 'O'},
- {"width", required_argument, NULL, 'W'},
- {"chosen", required_argument, NULL, 'C'},
- {"type", required_argument, NULL, 'T'},
- {"info", required_argument, &flag, 'i'},
- {NULL, 0, NULL, 0}
- };
- opt = getopt_long(argc, argv, optstring , longOpts, &longIndex);
- while( opt != -1 ) {
- switch(opt) {
- case 'E':
- if(!isNumber(optarg))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -E! %s - не целое число!\n", optarg);
- return 0;
- }
- if(!isNumber(argv[optind]))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -E! %s - не целое число!\n", argv[optind]);
- return 0;
- }
- arg.end[0] = atoi(optarg);
- arg.end[1] = atoi(argv[optind]);
- break;
- case 'T':
- if(!isNumber(optarg))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -T! %s - не целое число!\n", optarg);
- return 0;
- }
- if (atoi(optarg) < 0 || atoi(optarg) > 3) {
- printf("Ошибка! %s - такого типа рамки не существует!\n", optarg);
- return 0;
- }
- arg.type = atoi(optarg);
- break;
- case 'S':
- if(!isNumber(optarg))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -S! %s - не целое число!\n", optarg);
- return 0;
- }
- if(!isNumber(argv[optind]))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -S! %s - не целое число!\n", argv[optind]);
- return 0;
- }
- arg.start[0] = atoi(optarg);
- arg.start[1] = atoi(argv[optind]);
- break;
- case 'N':
- if(!isNumber(optarg))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -N! %s - не целое число!\n", optarg);
- return 0;
- }
- if(!isNumber(argv[optind]))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -N! %s - не целое число!\n", argv[optind]);
- return 0;
- }
- arg.nevv[0] = atoi(optarg);
- arg.nevv[1] = atoi(argv[optind]);
- break;
- case 'W':
- if(!isNumber(optarg))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -W! %s - не целое число!\n", optarg);
- return 0;
- }
- if (atoi(optarg) >= min(image.width, image.height) / 4 || atoi(optarg) < 0) {
- printf("Ошибка! Слишком большая ширина узора рамки или она меньше нуля.\n");
- return 0;
- }
- arg.width = atoi(optarg);
- break;
- case 'O':
- if(!isNumber(optarg))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -O! %s - не целое число!\n", optarg);
- return 0;
- }
- if(!isNumber(argv[optind]))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -O! %s - не целое число!\n", argv[optind]);
- return 0;
- }
- if(!isNumber(argv[optind]))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -O! %s - не целое число!\n", argv[optind + 1]);
- return 0;
- }
- if (atoi(optarg) > 255 || atoi(argv[optind]) > 255 || atoi(argv[optind + 1]) > 255
- || atoi(optarg) < 0 || atoi(argv[optind]) < 0 || atoi(argv[optind + 1]) < 0)
- {
- printf("Ошибка! Такого цвета не существует!\n");
- return 0;
- }
- arg.origin[0] = atoi(optarg);
- arg.origin[1] = atoi(argv[optind]);
- arg.origin[2] = atoi(argv[optind + 1]);
- break;
- case 'C':
- if(!isNumber(optarg))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -C! %s - не целое число!\n", optarg);
- return 0;
- }
- if(!isNumber(argv[optind]))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -C! %s - не целое число!\n", argv[optind]);
- return 0;
- }
- if(!isNumber(argv[optind]))
- {
- printf("Ошибка! Не корректно введены аргументы для флага -C! %s - не целое число!\n", argv[optind + 1]);
- return 0;
- }
- if (atoi(optarg) > 255 || atoi(argv[optind]) > 255 || atoi(argv[optind + 1]) > 255
- || atoi(optarg) < 0 || atoi(argv[optind]) < 0 || atoi(argv[optind + 1]) < 0)
- {
- printf("Ошибка! Такого цвета не существует!\n");
- return 0;
- }
- arg.chosen[0] = atoi(optarg);
- arg.chosen[1] = atoi(argv[optind]);
- arg.chosen[2] = atoi(argv[optind + 1]);
- break;
- case 'n':
- printHelp();
- break;
- case 'i':
- flag = 'i';
- break;
- case 's':
- flag = 's';
- break;
- case 'c':
- flag = 'c';
- break;
- case 'f':
- flag = 'f';
- break;
- case 'h':
- flag = 'h';
- break;
- default:
- printf("Такого флага не существует!\n");
- return 0;
- }
- opt = getopt_long(argc, argv, optstring , longOpts, &longIndex);
- }
- switch(flag){
- case'c':
- if (arg.start[0] == -1 || arg.start[1] == -1 || arg.end[0] == -1 || arg.end[1] == -1 ||
- arg.nevv[0] == -1 || arg.nevv[1] == -1) {
- printf("Неправильно заданы аргументы!\n");
- break;
- }
- if(arg.start[0] < 0 || arg.start[0] > image.width ||
- arg.start[1] < 0 || arg.start[1] > image.height ||
- arg.end[0] > image.width || arg.end[0] < 0 ||
- arg.end[1] > image.height || arg.end[1] < 0 ||
- arg.start[0] > arg.end[0] ||
- arg.start[1] > arg.end[1] ||
- arg.nevv[0] < 0 || arg.nevv[1] < 0 ||
- arg.nevv[0] > image.width || arg.nevv[1] > image.height)
- {
- printf("Область копирования не является корректной\n");
- break;
- }
- else
- {
- copyAndPaste(&image, arg.start[0], arg.start[1], arg.end[0], arg.end[1], arg.nevv[0], arg.nevv[1]);
- }
- break;
- case 'f':
- if (arg.chosen[0] == -1 || arg.chosen[1] == -1 || arg.chosen[2] == -1 || arg.width == -1) {
- printf("Неправильно заданы аргументы!\n");
- break;
- }
- drawFrame(&image, arg.chosen[0], arg.chosen[1], arg.chosen[2], arg.width, arg.type);
- break;
- case 's':
- if (arg.chosen[0] == -1 || arg.chosen[1] == -1 || arg.chosen[2] == -1
- || arg.origin[0] == -1 || arg.origin[1] == -1 || arg.origin[2] == -1) {
- printf("Неправильно заданы аргументы!\n");
- break;
- }
- swap_colors(&image, arg.origin[0], arg.origin[1], arg.origin[2], arg.chosen[0], arg.chosen[1], arg.chosen[2]);
- break;
- case 'n':
- printHelp();
- break;
- case 'i':
- printf("Width = %d\n", image.width);
- printf("Heigth = %d\n", image.height);
- break;
- }
- write_png_file(argv[argc - 1], &image);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement