Advertisement
Guest User

Untitled

a guest
May 25th, 2019
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.10 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5.  
  6. #define PATH "/home/olyaave/CLionProjects/CourseWork/bat.bmp"
  7. #define PATH_OUT "/home/olyaave/CLionProjects/CourseWork/result.bmp"
  8.  
  9. #pragma pack(push, 1)
  10. typedef struct BmpHeader {
  11. unsigned char b1, b2; // Символы BM (2 байта)
  12. unsigned int size; // Размер файла (4 байта)
  13. unsigned short notUse1; // (2 байта)
  14. unsigned short notUse2; // (2 байта)
  15. unsigned int massPos; // Местанахождение данных растрового массива (4 байта)
  16.  
  17. unsigned int headerLength; // Длина этого заголовка (4 байта)
  18. unsigned int width; // Ширина изображения (4 байта)
  19. unsigned int height; // Высота изображения (4 байта)
  20. unsigned short colorPlaneNumber; // Число цветовых плоскостей (2 байта)
  21. unsigned short bitPixel; // Бит/пиксель (2 байта)
  22. unsigned int compressMethod;// Метод сжатия (4 байта)
  23. unsigned int massLength; // Длинна массива с мусором (4 байта)
  24. unsigned int massWidth; // Ширина массива с мусором (4 байта)
  25. unsigned int massHeight; // Высота массива с мусором (4 байта)
  26. unsigned int colorNumber; // Число цветов изображения (4 байта)
  27. unsigned int generalColorNumber; // Число основных цветов (4 байта)
  28.  
  29. } bmpHeader;
  30. #pragma pack(pop)
  31.  
  32. typedef struct IMAGE {
  33. unsigned char b;
  34. unsigned char g;
  35. unsigned char r;
  36. } IMAGE;
  37.  
  38.  
  39. struct Point{
  40. int x;
  41. int y;
  42. };
  43.  
  44. struct Rectangle {
  45. int leftX;
  46. int leftY;
  47. int rightX;
  48. int rightY;
  49. };
  50.  
  51. int saveBMP(char* way, bmpHeader *V, int width);
  52.  
  53. IMAGE** img; // Изображение
  54. IMAGE** pic; // Для рамки
  55. RECT** rect; // Флаги для прямоугольников
  56.  
  57.  
  58. IMAGE chooseColor(int key){
  59. IMAGE color;
  60. switch(key){
  61. case 1: { return (IMAGE){255, 255, 255};}
  62. case 2: { return (IMAGE){255, 255, 0};}
  63. case 3: { return (IMAGE){0, 102, 0};}
  64. case 4: { color = (IMAGE){0, 102, 255}; break;}
  65. case 5: { color = (IMAGE){0, 0, 0}; break;}
  66. case 6: { color = (IMAGE){255, 0, 0}; break;}
  67. }
  68. return color;
  69. }
  70.  
  71. // Для рамки с линиями
  72. int line(int t, int s, int w, int h){
  73. IMAGE color = chooseColor(1);
  74. int diag = sqrt(2)*t ;
  75. for (int c = s; t < h ; c++) { //заполнение линии
  76. pic[t++][c] = color;
  77. }
  78. return 0;
  79. }
  80.  
  81. int allLine(int x, int y, int w, int h){
  82. int count = 0;
  83. printf("%d\n", w+h);
  84. for (int c = w + h; c > 0; c--){
  85. line(0, c, w, h);
  86. count++;
  87. if (count == 100) {
  88. c = c - 100;
  89. count = 0;
  90. }
  91. }
  92. return 0;
  93. }
  94.  
  95. // Для рамки с кругами
  96. void putpixel(int x, int y, int r){
  97. IMAGE color = chooseColor(5);
  98. for(int i = 0; i < r; i++)
  99. pic[x-i][y-i] = color;
  100. }
  101.  
  102. void circle(int xc, int yc, int r, int flag)
  103. {
  104. int x = 0, y = r, d = 2 * (1 - r);
  105. putpixel(xc + r, yc, r);
  106. putpixel(xc - r, yc, r);
  107.  
  108. while(y > 0)
  109. {
  110. putpixel(xc + x, yc + y, r);
  111. putpixel(xc + x, yc - y, r);
  112. putpixel(xc - x, yc + y, r);
  113. putpixel(xc - x, yc - y, r);
  114. if(d + y > 0)
  115. {
  116. y -= 1;
  117. d -= (2 * y) - 1;
  118. }
  119. if(x > d)
  120. {
  121. x += 1;
  122. d += (2 * x) + 1;
  123. }
  124. }
  125. }
  126.  
  127. // Считывание изображения
  128. int readBMP(char* way, bmpHeader *V){
  129. bmpHeader bmp;
  130. FILE* file;
  131. file = fopen(way, "rb");
  132. if (!file) return 0;
  133. size_t b = fread(&bmp, sizeof(bmp), 1, file);
  134. if (bmp.b1 != 'B' || bmp.b2 != 'M' || bmp.bitPixel != 24){
  135. printf("Error_bmpHeader\n");
  136. fclose(file);
  137. return 0;
  138. }
  139. img = calloc(bmp.width, sizeof(*img));
  140. for(int i = 0; i < bmp.width; i++)
  141. img[i] = calloc(bmp.height, sizeof(img[i]));
  142.  
  143. for (int i = 0; i < bmp.height; i++) //???
  144. for(int j = 0; j < bmp.width; j++){
  145. fread(&img[i][j], sizeof(IMAGE), 1, file);
  146. }
  147. *V = bmp;
  148. //printf("bmp = %d", bmp.width);
  149. fclose(file);
  150. return 1;
  151. }
  152.  
  153. int removeColor(int *w, int *h){ // Замена цвета
  154. int c_1, c_2;
  155. printf("Палитра цветов:\n (1) Белый (2) Желтый (3) Зеленый\n (4) Синий (5) Черный (6) Красный\n");
  156. printf("Введите цвет, который хотите заменить: ");
  157. scanf("%d", &c_1);
  158. printf("Введите цвет, на который хотите заменить: ");
  159. scanf("%d", &c_2);
  160.  
  161. IMAGE color_1, color_2;
  162. color_1 = chooseColor(c_1);
  163. color_2 = chooseColor(c_2);
  164.  
  165. for (int i = 0; i < *h; i++) {
  166. for (int j = 0; j < *w; j++)
  167. if (img[i][j].r == color_1.r && img[i][j].g == color_1.g && color_1.b == img[i][j].b)
  168. //if (img[i][j] == color_1)
  169. {
  170. img[i][j] = color_2;
  171. }
  172. }
  173. return 0;
  174. }
  175.  
  176. int makeFrame(int *w, int *h) { // Создание рамки
  177. int frame = 0, color, width;
  178.  
  179. printf("(1) Линии (2) Спираль (3) какой-то узор\n");
  180. printf("Выберите узор: ");
  181. int k = scanf("%d", &frame);
  182. while (getchar() != '\n');
  183. while (!k || frame > 3 || frame < 0) {
  184. printf("Может все-таки выберите узор: ");
  185. k = scanf("%d", &frame);
  186. while (getchar() != '\n');
  187. }
  188. if (frame != 1) {
  189. printf("(1) Белый (2) Желтый (3) Зеленый (4) Синий (5) Черный (6) Красный\n");
  190. printf("Выберите цвет: ");
  191. int c = scanf("%d", &color);
  192. while (getchar() != '\n');
  193. while (!c || color > 6 || color < 0) {
  194. printf("Может все-таки цвет: ");
  195. c = scanf("%d", &color);
  196. while (getchar() != '\n');
  197. }
  198. }
  199. printf("Введите ширину рамки(в пикселях): ");
  200. int s = scanf("%d", &width);
  201. while (getchar() != '\n');
  202. while (s < 1) {
  203. printf("Нужно ввести число: ");
  204. s = scanf("%d", &width);
  205. while (getchar() != '\n');
  206. }
  207.  
  208. IMAGE color_rgb = chooseColor(color);
  209.  
  210. pic = calloc(*w + width * 2, sizeof(*pic));
  211. for (int i = 0; i < *w + width * 2; i++)
  212. pic[i] = calloc(*h + width * 2, sizeof(pic[i]));
  213.  
  214.  
  215. if (frame != 1) {
  216. for (int i = 0; i < *h + width * 2; i++)
  217. for (int j = 0; j < *w + width * 2; j++) {
  218. if (i > width && i < width + *h && j > width && j < width + *w)
  219. pic[i][j] = img[i - width][j - width];
  220. else
  221. pic[i][j] = color_rgb;
  222. }
  223. }
  224. else if (frame == 1) {
  225.  
  226. IMAGE col1 = (IMAGE){18, 18, 255}; // red
  227. IMAGE col2 = (IMAGE){184, 80, 15}; // blue
  228. for (int i = 0; i < *h + width * 2; i++) {
  229. for (int j = 0; j < *w + width * 2; j++) {
  230. pic[i][j] = col2;
  231.  
  232. }
  233. }
  234. allLine(0, 0, *w + 2 * width, *h + 2 * width);
  235. int dots = (int)(width/5);
  236. for (int i = 0; i < *h + width * 2; i++)
  237. for (int j = 0; j < *w + width * 2; j++) {
  238. if (i > width && i < width + *h && j > width && j < width + *w)
  239. pic[i][j] = img[i - width][j - width];
  240. else if (i > width - dots && i < width + dots + *h && j > width - dots && j < width + dots + *w)
  241. pic[i][j] = col1;
  242. }
  243. }
  244. if (frame == 2) {
  245. int times = (int) ((*w + width * 2) / width);
  246. //printf("%d", times);
  247. int per = 3;
  248. int indent = (int) ((*w + width * 2 - times * width) / per); //привязать вертикальные линии к высоте
  249. for (int i = (int) (width * 2 / per);
  250. i < ((times) * width + (int) (width * 2 / per)); i = i + (int) (width * 2 / per)) {
  251. circle((int) (width * 2 / per), i, (int) (width / per), 2);
  252. circle((int) (width * 2 / per) + width + *h, i, (int) (width / per), 2);
  253. }
  254. times = (int) ((*h + width) / width);
  255. //printf("times 2 = %d\n", times);
  256. for (int i = (int) (width / per) + width; i < ((times) * (width) + (int) (width)); i = i + (int) width * 2 / per) {
  257. circle(i, (int) (width * 2 / per), (int) (width / per), 2);
  258. circle(i, (int) (width * 2 / per) + width + *w, (int) (width / per), 2);
  259. }
  260. }
  261.  
  262. return width;
  263. }
  264. // проверить соседние точки
  265. // массив прямоугольников
  266.  
  267. // (200, 400 (600, 700)
  268.  
  269. int compFind(struct RGBA that, struct RGBA with){
  270.  
  271. if (that.red == with.red && that.green == with.green && that.blue == with.blue && that.alpha == with.alpha)
  272. return 1;
  273. return 0;
  274. }
  275.  
  276. int checBord(struct Png* image, int leftX, int leftY, int rightX, int rightY, struct RGBA that){
  277.  
  278. if (leftX)
  279. for (int i = leftY; i < rightY; i++) {
  280. if (compFind(that, image->pixel[i][leftX - 1]))
  281. return 1;
  282. }
  283.  
  284. if (leftY)
  285. for (int j = leftX; rightX < j; j++) {
  286. if (compFind(that, image->pixel[leftY - 1][j]))
  287. return 1;
  288. }
  289. if (rightX != image->width)
  290. for (int i = leftY; i < rightY; i++) {
  291. if (compFind(that, image->pixel[i][rightX]))
  292. return 1;
  293. }
  294. if (rightY != image->height)
  295. for (int j = leftX; j < rightX; j++){
  296. if (compFind(that, image->pixel[rightY][j]))
  297. return 1;
  298. }
  299. return 0;
  300. }
  301.  
  302. void image_fill2(struct Png* image, int x, int y, struct RGBA that) {
  303. image->pixel[y][x].flag = 2;
  304. // Получим размеры изображения
  305. int imw = image->width;
  306. int imh = image->height;
  307.  
  308. // Выделим памяти для складирования координат, которые еще предстоит залить
  309. int STACK_SIZE = (imw+2)*(imh+2);
  310. int *floodfill_stackx = (int*)malloc(STACK_SIZE*sizeof(int));
  311. int *floodfill_stacky = (int*)malloc(STACK_SIZE*sizeof(int));
  312.  
  313. if (floodfill_stacky == NULL || floodfill_stackx == NULL)
  314. return;
  315.  
  316. int stack_head = 0;
  317. int stack_tail = 0;
  318.  
  319.  
  320. floodfill_stackx[stack_head] = x;
  321. floodfill_stacky[stack_head] = y;
  322. stack_head++;
  323.  
  324. // Пока не кончится память или точки на изображении
  325. while (stack_head < STACK_SIZE && stack_head > stack_tail) {
  326. x = floodfill_stackx[stack_tail];
  327. y = floodfill_stacky[stack_tail];
  328. stack_tail++;
  329.  
  330. if (x >= 0 && y >= 0 && x < imw && y < imh) {
  331.  
  332. // Проверим точку справа, если она не залита, то зальем
  333. if (x + 1 == imw)
  334. continue;
  335. if (image->pixel[y][x + 1].red == that.red &&
  336. image->pixel[y][x + 1].green == that.green &&
  337. image->pixel[y][x + 1].blue == that.blue &&
  338. image->pixel[y][x + 1].alpha == that.alpha &&
  339. image->pixel[y][x + 1].flag == 0) {
  340.  
  341. floodfill_stackx[stack_head] = x + 1;
  342. floodfill_stacky[stack_head] = y;
  343. image->pixel[y][x + 1].flag = 2;
  344. stack_head++;
  345. }
  346. // Проверим точку слева, если она не залита, то зальем
  347. if (x - 1 == -1)
  348. continue;
  349. if (image->pixel[y][x - 1].red == that.red &&
  350. image->pixel[y][x - 1].green == that.green &&
  351. image->pixel[y][x - 1].blue == that.blue &&
  352. image->pixel[y][x - 1].alpha == that.alpha &&
  353. image->pixel[y][x - 1].flag == 0) {
  354.  
  355. floodfill_stackx[stack_head] = x - 1;
  356. floodfill_stacky[stack_head] = y;
  357. image->pixel[y][x - 1].flag = 2;
  358. stack_head++;
  359. }
  360. // Проверим точку снизу, если она не залита, то зальем
  361. if (y + 1 == imh)
  362. continue;
  363. if (image->pixel[y + 1][x].red == that.red &&
  364. image->pixel[y + 1][x].green == that.green &&
  365. image->pixel[y + 1][x].blue == that.blue &&
  366. image->pixel[y + 1][x].alpha == that.alpha &&
  367. image->pixel[y + 1][x].flag == 0) {
  368.  
  369. floodfill_stackx[stack_head] = x;
  370. floodfill_stacky[stack_head] = y + 1;
  371. image->pixel[y + 1][x].flag = 2;
  372. stack_head++;
  373. }
  374. // Проверим точку сверху, если она не залита, то зальем
  375. if (y - 1 == -1)
  376. continue;
  377. if (image->pixel[y - 1][x].red == that.red &&
  378. image->pixel[y - 1][x].green == that.green &&
  379. image->pixel[y - 1][x].blue == that.blue &&
  380. image->pixel[y - 1][x].alpha == that.alpha &&
  381. image->pixel[y - 1][x].flag == 0) {
  382.  
  383. floodfill_stackx[stack_head] = x;
  384. floodfill_stacky[stack_head] = y - 1;
  385. image->pixel[y - 1][x].flag = 2;
  386. stack_head++;
  387. }
  388. }
  389. }
  390. // Освободим память
  391. free(floodfill_stacky);
  392. free(floodfill_stackx);
  393. }
  394.  
  395. struct Point find_clr(struct Png* image, struct RGBA that){
  396. int x, y;
  397. struct Point tmp;
  398. tmp.x = -1;
  399.  
  400. for (y = 0; y < image->height; y++) {
  401. for (x = 0; x < image->width; x++) {
  402. if (compFind(image->pixel[y][x], that) && image->pixel[y][x].flag == 0) {
  403. tmp.x = x;
  404. tmp.y = y;
  405. image_fill2(image, x, y, that);
  406. return tmp;
  407. }
  408. }
  409. }
  410. return tmp;
  411. }
  412.  
  413. void find_rectangle(struct Png* image, struct RGBA that, struct RGBA onWhat, int size){
  414.  
  415. int x = 0, y = 0;
  416. int i = 0, j = 0;
  417.  
  418. int leftX;
  419. int leftY;
  420. int rightX;
  421. int rightY;
  422.  
  423. int sizeXL;
  424. int sizeYL;
  425. int sizeXR;
  426. int sizeYR;
  427.  
  428. int flag = 0;
  429. int count = 1;
  430.  
  431. struct Rectangle* arr = NULL;
  432. struct Point tmp = find_clr(image, that);
  433.  
  434.  
  435. while(tmp.x != -1){ //
  436. leftY = tmp.y;
  437. leftX = tmp.x;
  438. i = 0;
  439. j = 0;
  440. flag = 0;
  441.  
  442. while(leftY + i < image->height && image->pixel[leftY + i][leftX].flag == 2){
  443. i++;
  444. }
  445. rightY = leftY + i;
  446.  
  447. while(leftX + j < image->width && image->pixel[leftY][leftX + j].flag == 2){
  448. j++;
  449. }
  450. rightX = leftX + j;
  451.  
  452.  
  453. for (y = leftY; y < rightY; y++) {
  454. for (x = leftX; x < rightX; x++)
  455. if (image->pixel[y][x].flag != 2) {
  456. flag = 1;
  457. break;
  458. }
  459. if (flag)
  460. break;
  461. }
  462.  
  463. if (checBord(image, leftX, leftY, rightX, rightY, that))
  464. flag = 1;
  465.  
  466.  
  467. if (flag != 1) {
  468. arr = (struct Rectangle*)realloc(arr, count * sizeof(struct Rectangle));
  469. arr[count - 1].leftY = leftY;
  470. arr[count - 1].leftX = leftX;
  471. arr[count - 1].rightY = rightY;
  472. arr[count - 1].rightX = rightX;
  473. count++;
  474. }
  475. tmp = find_clr(image, that);
  476. }
  477.  
  478.  
  479. for (int a = 0; a < count - 1; a++){
  480.  
  481. sizeXL = arr[a].leftX - size < 0 ? 0 : arr[a].leftX - size;
  482. sizeYL = arr[a].leftY - size < 0 ? 0 : arr[a].leftY - size;
  483. sizeXR = arr[a].rightX + size > image->width ? image->width : arr[a].rightX + size;
  484. sizeYR = arr[a].rightY + size > image->height ? image->height : arr[a].rightY + size;
  485.  
  486.  
  487. for (j = sizeYL; j < arr[a].leftY; j++)
  488. for (i = sizeXL; i < sizeXR; i++)
  489. image->pixel[j][i] = onWhat;
  490.  
  491. for (j = arr[a].rightY; j < sizeYR; j++)
  492. for (i = sizeXL; i < sizeXR; i++)
  493. image->pixel[j][i] = onWhat;
  494.  
  495. for (i = sizeXL; i < arr[a].leftX; i++)
  496. for (j = arr[a].leftY; j < arr[a].rightY; j++)
  497. image->pixel[j][i] = onWhat;
  498.  
  499. for (i = arr[a].rightX; i < sizeXR; i++)
  500. for (j = arr[a].leftY; j < arr[a].rightY; j++)
  501. image->pixel[j][i] = onWhat;
  502.  
  503. }
  504.  
  505. for (int a = 0; a < count - 1; a++)
  506. for (j = arr[a].leftY; j < arr[a].rightY; j++)
  507. for (i = arr[a].leftX; i < arr[a].rightX; i++)
  508. image->pixel[j][i] = that;
  509.  
  510.  
  511. }
  512.  
  513.  
  514. int menu(int *w, int *h){
  515. int key;
  516. printf("Данная программа имеет следующий функционал:\n");
  517. printf(" [1] Заменить цвета заданного цвета на другой.\n");
  518. printf(" [2] Сделать рамку\n");
  519. printf(" [3] Найти все прямоугольники\n");
  520. printf("Выберита функцию по обработке файла: ");
  521. int k = scanf("%d", &key);
  522. while (getchar() != '\n');
  523. while (!k || key > 3 || key < 0){
  524. printf("Может все-таки выберите узор: ");
  525. k = scanf("%d", &key);
  526. while (getchar() != '\n');
  527. }
  528. switch(key){
  529. case 1:
  530. return removeColor(w, h);
  531. case 2:
  532. return makeFrame(w, h);
  533. case 3:
  534. return normRect(w, h);
  535.  
  536.  
  537. }
  538. return 0;
  539. }
  540.  
  541. int saveBMP(char* way, bmpHeader *V, int width){
  542. bmpHeader bmp = *V;
  543. FILE* file;
  544. int i, j;
  545. file = fopen(way,"wb");
  546. printf("я сохранился\n");
  547. if(file == NULL) return 0;
  548. if (pic != NULL){
  549. printf("pic существует");
  550. bmp.height = bmp.height + width*2;
  551. bmp.width = bmp.width + width*2;
  552. fwrite(&bmp, sizeof(bmp), 1, file);
  553. for (i = 0; i < bmp.height; i++) {
  554. for (j = 0; j < bmp.width; j++)
  555. fwrite(&pic[i][j], sizeof(pic[i][j]), 1, file);
  556. }
  557. }
  558. else {
  559. fwrite(&bmp, sizeof(bmp), 1, file);
  560. for (i = 0; i < bmp.height; i++)
  561. for (j = 0; j < bmp.width; j++)
  562. fwrite(&img[i][j], sizeof(img[i][j]), 1, file);
  563. }
  564. fclose(file);
  565. return 1;
  566. }
  567.  
  568.  
  569. int main(){
  570. bmpHeader bmp;
  571. if (!readBMP(PATH, &bmp)){
  572. printf("Error_READ\n");
  573. return 0;
  574. }
  575. int width = menu(&(bmp.width), &(bmp.height));
  576.  
  577. if (!saveBMP(PATH_OUT, &bmp, width)) {
  578. printf("Error_SAVE\n");
  579. return 0;
  580. }
  581. return 0;
  582. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement