Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #define PATH "/home/olyaave/CLionProjects/CourseWork/bat.bmp"
- #define PATH_OUT "/home/olyaave/CLionProjects/CourseWork/result.bmp"
- #pragma pack(push, 1)
- typedef struct BmpHeader {
- unsigned char b1, b2; // Символы BM (2 байта)
- unsigned int size; // Размер файла (4 байта)
- unsigned short notUse1; // (2 байта)
- unsigned short notUse2; // (2 байта)
- unsigned int massPos; // Местанахождение данных растрового массива (4 байта)
- unsigned int headerLength; // Длина этого заголовка (4 байта)
- unsigned int width; // Ширина изображения (4 байта)
- unsigned int height; // Высота изображения (4 байта)
- unsigned short colorPlaneNumber; // Число цветовых плоскостей (2 байта)
- unsigned short bitPixel; // Бит/пиксель (2 байта)
- unsigned int compressMethod;// Метод сжатия (4 байта)
- unsigned int massLength; // Длинна массива с мусором (4 байта)
- unsigned int massWidth; // Ширина массива с мусором (4 байта)
- unsigned int massHeight; // Высота массива с мусором (4 байта)
- unsigned int colorNumber; // Число цветов изображения (4 байта)
- unsigned int generalColorNumber; // Число основных цветов (4 байта)
- } bmpHeader;
- #pragma pack(pop)
- typedef struct IMAGE {
- unsigned char b;
- unsigned char g;
- unsigned char r;
- } IMAGE;
- struct Point{
- int x;
- int y;
- };
- struct Rectangle {
- int leftX;
- int leftY;
- int rightX;
- int rightY;
- };
- int saveBMP(char* way, bmpHeader *V, int width);
- IMAGE** img; // Изображение
- IMAGE** pic; // Для рамки
- RECT** rect; // Флаги для прямоугольников
- IMAGE chooseColor(int key){
- IMAGE color;
- switch(key){
- case 1: { return (IMAGE){255, 255, 255};}
- case 2: { return (IMAGE){255, 255, 0};}
- case 3: { return (IMAGE){0, 102, 0};}
- case 4: { color = (IMAGE){0, 102, 255}; break;}
- case 5: { color = (IMAGE){0, 0, 0}; break;}
- case 6: { color = (IMAGE){255, 0, 0}; break;}
- }
- return color;
- }
- // Для рамки с линиями
- int line(int t, int s, int w, int h){
- IMAGE color = chooseColor(1);
- int diag = sqrt(2)*t ;
- for (int c = s; t < h ; c++) { //заполнение линии
- pic[t++][c] = color;
- }
- return 0;
- }
- int allLine(int x, int y, int w, int h){
- int count = 0;
- printf("%d\n", w+h);
- for (int c = w + h; c > 0; c--){
- line(0, c, w, h);
- count++;
- if (count == 100) {
- c = c - 100;
- count = 0;
- }
- }
- return 0;
- }
- // Для рамки с кругами
- void putpixel(int x, int y, int r){
- IMAGE color = chooseColor(5);
- for(int i = 0; i < r; i++)
- pic[x-i][y-i] = color;
- }
- void circle(int xc, int yc, int r, int flag)
- {
- int x = 0, y = r, d = 2 * (1 - r);
- putpixel(xc + r, yc, r);
- putpixel(xc - r, yc, r);
- while(y > 0)
- {
- putpixel(xc + x, yc + y, r);
- putpixel(xc + x, yc - y, r);
- putpixel(xc - x, yc + y, r);
- putpixel(xc - x, yc - y, r);
- if(d + y > 0)
- {
- y -= 1;
- d -= (2 * y) - 1;
- }
- if(x > d)
- {
- x += 1;
- d += (2 * x) + 1;
- }
- }
- }
- // Считывание изображения
- int readBMP(char* way, bmpHeader *V){
- bmpHeader bmp;
- FILE* file;
- file = fopen(way, "rb");
- if (!file) return 0;
- size_t b = fread(&bmp, sizeof(bmp), 1, file);
- if (bmp.b1 != 'B' || bmp.b2 != 'M' || bmp.bitPixel != 24){
- printf("Error_bmpHeader\n");
- fclose(file);
- return 0;
- }
- img = calloc(bmp.width, sizeof(*img));
- for(int i = 0; i < bmp.width; i++)
- img[i] = calloc(bmp.height, sizeof(img[i]));
- for (int i = 0; i < bmp.height; i++) //???
- for(int j = 0; j < bmp.width; j++){
- fread(&img[i][j], sizeof(IMAGE), 1, file);
- }
- *V = bmp;
- //printf("bmp = %d", bmp.width);
- fclose(file);
- return 1;
- }
- int removeColor(int *w, int *h){ // Замена цвета
- int c_1, c_2;
- printf("Палитра цветов:\n (1) Белый (2) Желтый (3) Зеленый\n (4) Синий (5) Черный (6) Красный\n");
- printf("Введите цвет, который хотите заменить: ");
- scanf("%d", &c_1);
- printf("Введите цвет, на который хотите заменить: ");
- scanf("%d", &c_2);
- IMAGE color_1, color_2;
- color_1 = chooseColor(c_1);
- color_2 = chooseColor(c_2);
- for (int i = 0; i < *h; i++) {
- for (int j = 0; j < *w; j++)
- if (img[i][j].r == color_1.r && img[i][j].g == color_1.g && color_1.b == img[i][j].b)
- //if (img[i][j] == color_1)
- {
- img[i][j] = color_2;
- }
- }
- return 0;
- }
- int makeFrame(int *w, int *h) { // Создание рамки
- int frame = 0, color, width;
- printf("(1) Линии (2) Спираль (3) какой-то узор\n");
- printf("Выберите узор: ");
- int k = scanf("%d", &frame);
- while (getchar() != '\n');
- while (!k || frame > 3 || frame < 0) {
- printf("Может все-таки выберите узор: ");
- k = scanf("%d", &frame);
- while (getchar() != '\n');
- }
- if (frame != 1) {
- printf("(1) Белый (2) Желтый (3) Зеленый (4) Синий (5) Черный (6) Красный\n");
- printf("Выберите цвет: ");
- int c = scanf("%d", &color);
- while (getchar() != '\n');
- while (!c || color > 6 || color < 0) {
- printf("Может все-таки цвет: ");
- c = scanf("%d", &color);
- while (getchar() != '\n');
- }
- }
- printf("Введите ширину рамки(в пикселях): ");
- int s = scanf("%d", &width);
- while (getchar() != '\n');
- while (s < 1) {
- printf("Нужно ввести число: ");
- s = scanf("%d", &width);
- while (getchar() != '\n');
- }
- IMAGE color_rgb = chooseColor(color);
- pic = calloc(*w + width * 2, sizeof(*pic));
- for (int i = 0; i < *w + width * 2; i++)
- pic[i] = calloc(*h + width * 2, sizeof(pic[i]));
- if (frame != 1) {
- for (int i = 0; i < *h + width * 2; i++)
- for (int j = 0; j < *w + width * 2; j++) {
- if (i > width && i < width + *h && j > width && j < width + *w)
- pic[i][j] = img[i - width][j - width];
- else
- pic[i][j] = color_rgb;
- }
- }
- else if (frame == 1) {
- IMAGE col1 = (IMAGE){18, 18, 255}; // red
- IMAGE col2 = (IMAGE){184, 80, 15}; // blue
- for (int i = 0; i < *h + width * 2; i++) {
- for (int j = 0; j < *w + width * 2; j++) {
- pic[i][j] = col2;
- }
- }
- allLine(0, 0, *w + 2 * width, *h + 2 * width);
- int dots = (int)(width/5);
- for (int i = 0; i < *h + width * 2; i++)
- for (int j = 0; j < *w + width * 2; j++) {
- if (i > width && i < width + *h && j > width && j < width + *w)
- pic[i][j] = img[i - width][j - width];
- else if (i > width - dots && i < width + dots + *h && j > width - dots && j < width + dots + *w)
- pic[i][j] = col1;
- }
- }
- if (frame == 2) {
- int times = (int) ((*w + width * 2) / width);
- //printf("%d", times);
- int per = 3;
- int indent = (int) ((*w + width * 2 - times * width) / per); //привязать вертикальные линии к высоте
- for (int i = (int) (width * 2 / per);
- i < ((times) * width + (int) (width * 2 / per)); i = i + (int) (width * 2 / per)) {
- circle((int) (width * 2 / per), i, (int) (width / per), 2);
- circle((int) (width * 2 / per) + width + *h, i, (int) (width / per), 2);
- }
- times = (int) ((*h + width) / width);
- //printf("times 2 = %d\n", times);
- for (int i = (int) (width / per) + width; i < ((times) * (width) + (int) (width)); i = i + (int) width * 2 / per) {
- circle(i, (int) (width * 2 / per), (int) (width / per), 2);
- circle(i, (int) (width * 2 / per) + width + *w, (int) (width / per), 2);
- }
- }
- return width;
- }
- // проверить соседние точки
- // массив прямоугольников
- // (200, 400 (600, 700)
- int compFind(struct RGBA that, struct RGBA with){
- if (that.red == with.red && that.green == with.green && that.blue == with.blue && that.alpha == with.alpha)
- return 1;
- return 0;
- }
- int checBord(struct Png* image, int leftX, int leftY, int rightX, int rightY, struct RGBA that){
- if (leftX)
- for (int i = leftY; i < rightY; i++) {
- if (compFind(that, image->pixel[i][leftX - 1]))
- return 1;
- }
- if (leftY)
- for (int j = leftX; rightX < j; j++) {
- if (compFind(that, image->pixel[leftY - 1][j]))
- return 1;
- }
- if (rightX != image->width)
- for (int i = leftY; i < rightY; i++) {
- if (compFind(that, image->pixel[i][rightX]))
- return 1;
- }
- if (rightY != image->height)
- for (int j = leftX; j < rightX; j++){
- if (compFind(that, image->pixel[rightY][j]))
- return 1;
- }
- return 0;
- }
- void image_fill2(struct Png* image, int x, int y, struct RGBA that) {
- image->pixel[y][x].flag = 2;
- // Получим размеры изображения
- int imw = image->width;
- int imh = image->height;
- // Выделим памяти для складирования координат, которые еще предстоит залить
- int STACK_SIZE = (imw+2)*(imh+2);
- int *floodfill_stackx = (int*)malloc(STACK_SIZE*sizeof(int));
- int *floodfill_stacky = (int*)malloc(STACK_SIZE*sizeof(int));
- if (floodfill_stacky == NULL || floodfill_stackx == NULL)
- return;
- int stack_head = 0;
- int stack_tail = 0;
- floodfill_stackx[stack_head] = x;
- floodfill_stacky[stack_head] = y;
- stack_head++;
- // Пока не кончится память или точки на изображении
- while (stack_head < STACK_SIZE && stack_head > stack_tail) {
- x = floodfill_stackx[stack_tail];
- y = floodfill_stacky[stack_tail];
- stack_tail++;
- if (x >= 0 && y >= 0 && x < imw && y < imh) {
- // Проверим точку справа, если она не залита, то зальем
- if (x + 1 == imw)
- continue;
- if (image->pixel[y][x + 1].red == that.red &&
- image->pixel[y][x + 1].green == that.green &&
- image->pixel[y][x + 1].blue == that.blue &&
- image->pixel[y][x + 1].alpha == that.alpha &&
- image->pixel[y][x + 1].flag == 0) {
- floodfill_stackx[stack_head] = x + 1;
- floodfill_stacky[stack_head] = y;
- image->pixel[y][x + 1].flag = 2;
- stack_head++;
- }
- // Проверим точку слева, если она не залита, то зальем
- if (x - 1 == -1)
- continue;
- if (image->pixel[y][x - 1].red == that.red &&
- image->pixel[y][x - 1].green == that.green &&
- image->pixel[y][x - 1].blue == that.blue &&
- image->pixel[y][x - 1].alpha == that.alpha &&
- image->pixel[y][x - 1].flag == 0) {
- floodfill_stackx[stack_head] = x - 1;
- floodfill_stacky[stack_head] = y;
- image->pixel[y][x - 1].flag = 2;
- stack_head++;
- }
- // Проверим точку снизу, если она не залита, то зальем
- if (y + 1 == imh)
- continue;
- if (image->pixel[y + 1][x].red == that.red &&
- image->pixel[y + 1][x].green == that.green &&
- image->pixel[y + 1][x].blue == that.blue &&
- image->pixel[y + 1][x].alpha == that.alpha &&
- image->pixel[y + 1][x].flag == 0) {
- floodfill_stackx[stack_head] = x;
- floodfill_stacky[stack_head] = y + 1;
- image->pixel[y + 1][x].flag = 2;
- stack_head++;
- }
- // Проверим точку сверху, если она не залита, то зальем
- if (y - 1 == -1)
- continue;
- if (image->pixel[y - 1][x].red == that.red &&
- image->pixel[y - 1][x].green == that.green &&
- image->pixel[y - 1][x].blue == that.blue &&
- image->pixel[y - 1][x].alpha == that.alpha &&
- image->pixel[y - 1][x].flag == 0) {
- floodfill_stackx[stack_head] = x;
- floodfill_stacky[stack_head] = y - 1;
- image->pixel[y - 1][x].flag = 2;
- stack_head++;
- }
- }
- }
- // Освободим память
- free(floodfill_stacky);
- free(floodfill_stackx);
- }
- struct Point find_clr(struct Png* image, struct RGBA that){
- int x, y;
- struct Point tmp;
- tmp.x = -1;
- for (y = 0; y < image->height; y++) {
- for (x = 0; x < image->width; x++) {
- if (compFind(image->pixel[y][x], that) && image->pixel[y][x].flag == 0) {
- tmp.x = x;
- tmp.y = y;
- image_fill2(image, x, y, that);
- return tmp;
- }
- }
- }
- return tmp;
- }
- void find_rectangle(struct Png* image, struct RGBA that, struct RGBA onWhat, int size){
- int x = 0, y = 0;
- int i = 0, j = 0;
- int leftX;
- int leftY;
- int rightX;
- int rightY;
- int sizeXL;
- int sizeYL;
- int sizeXR;
- int sizeYR;
- int flag = 0;
- int count = 1;
- struct Rectangle* arr = NULL;
- struct Point tmp = find_clr(image, that);
- while(tmp.x != -1){ //
- leftY = tmp.y;
- leftX = tmp.x;
- i = 0;
- j = 0;
- flag = 0;
- while(leftY + i < image->height && image->pixel[leftY + i][leftX].flag == 2){
- i++;
- }
- rightY = leftY + i;
- while(leftX + j < image->width && image->pixel[leftY][leftX + j].flag == 2){
- j++;
- }
- rightX = leftX + j;
- for (y = leftY; y < rightY; y++) {
- for (x = leftX; x < rightX; x++)
- if (image->pixel[y][x].flag != 2) {
- flag = 1;
- break;
- }
- if (flag)
- break;
- }
- if (checBord(image, leftX, leftY, rightX, rightY, that))
- flag = 1;
- if (flag != 1) {
- arr = (struct Rectangle*)realloc(arr, count * sizeof(struct Rectangle));
- arr[count - 1].leftY = leftY;
- arr[count - 1].leftX = leftX;
- arr[count - 1].rightY = rightY;
- arr[count - 1].rightX = rightX;
- count++;
- }
- tmp = find_clr(image, that);
- }
- for (int a = 0; a < count - 1; a++){
- sizeXL = arr[a].leftX - size < 0 ? 0 : arr[a].leftX - size;
- sizeYL = arr[a].leftY - size < 0 ? 0 : arr[a].leftY - size;
- sizeXR = arr[a].rightX + size > image->width ? image->width : arr[a].rightX + size;
- sizeYR = arr[a].rightY + size > image->height ? image->height : arr[a].rightY + size;
- for (j = sizeYL; j < arr[a].leftY; j++)
- for (i = sizeXL; i < sizeXR; i++)
- image->pixel[j][i] = onWhat;
- for (j = arr[a].rightY; j < sizeYR; j++)
- for (i = sizeXL; i < sizeXR; i++)
- image->pixel[j][i] = onWhat;
- for (i = sizeXL; i < arr[a].leftX; i++)
- for (j = arr[a].leftY; j < arr[a].rightY; j++)
- image->pixel[j][i] = onWhat;
- for (i = arr[a].rightX; i < sizeXR; i++)
- for (j = arr[a].leftY; j < arr[a].rightY; j++)
- image->pixel[j][i] = onWhat;
- }
- for (int a = 0; a < count - 1; a++)
- for (j = arr[a].leftY; j < arr[a].rightY; j++)
- for (i = arr[a].leftX; i < arr[a].rightX; i++)
- image->pixel[j][i] = that;
- }
- int menu(int *w, int *h){
- int key;
- printf("Данная программа имеет следующий функционал:\n");
- printf(" [1] Заменить цвета заданного цвета на другой.\n");
- printf(" [2] Сделать рамку\n");
- printf(" [3] Найти все прямоугольники\n");
- printf("Выберита функцию по обработке файла: ");
- int k = scanf("%d", &key);
- while (getchar() != '\n');
- while (!k || key > 3 || key < 0){
- printf("Может все-таки выберите узор: ");
- k = scanf("%d", &key);
- while (getchar() != '\n');
- }
- switch(key){
- case 1:
- return removeColor(w, h);
- case 2:
- return makeFrame(w, h);
- case 3:
- return normRect(w, h);
- }
- return 0;
- }
- int saveBMP(char* way, bmpHeader *V, int width){
- bmpHeader bmp = *V;
- FILE* file;
- int i, j;
- file = fopen(way,"wb");
- printf("я сохранился\n");
- if(file == NULL) return 0;
- if (pic != NULL){
- printf("pic существует");
- bmp.height = bmp.height + width*2;
- bmp.width = bmp.width + width*2;
- fwrite(&bmp, sizeof(bmp), 1, file);
- for (i = 0; i < bmp.height; i++) {
- for (j = 0; j < bmp.width; j++)
- fwrite(&pic[i][j], sizeof(pic[i][j]), 1, file);
- }
- }
- else {
- fwrite(&bmp, sizeof(bmp), 1, file);
- for (i = 0; i < bmp.height; i++)
- for (j = 0; j < bmp.width; j++)
- fwrite(&img[i][j], sizeof(img[i][j]), 1, file);
- }
- fclose(file);
- return 1;
- }
- int main(){
- bmpHeader bmp;
- if (!readBMP(PATH, &bmp)){
- printf("Error_READ\n");
- return 0;
- }
- int width = menu(&(bmp.width), &(bmp.height));
- if (!saveBMP(PATH_OUT, &bmp, width)) {
- printf("Error_SAVE\n");
- return 0;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement