Advertisement
Guest User

Untitled

a guest
Dec 16th, 2019
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.87 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include <string.h>
  5.  
  6. struct PgmImage
  7. {
  8. int width;
  9. int height;
  10. unsigned short depth; //głębia szarości
  11. unsigned short** pixels; //tablica wskaźników (macierz pixeli)
  12. };
  13.  
  14. typedef struct PgmImage PgmImage; // typedef - zamienia struct pgmimage na pgmimage
  15.  
  16. struct PgmImageDb
  17. {
  18. PgmImage* images;
  19. int length;
  20. int index; //aktywny indeks
  21. };
  22.  
  23. typedef struct PgmImageDb PgmImageDb;
  24.  
  25.  
  26.  
  27.  
  28. int ReadInteger(const char* message)
  29. {
  30. int number;
  31.  
  32. while (1) //petla wykonuje sie dopoki uzytkownik nie poda wlasciwej wartosci liczbowej (int)
  33. {
  34. printf(message);
  35.  
  36. if (scanf("%d", &number) == 1)
  37. {
  38. break;
  39. }
  40.  
  41. printf("Podano nieprawidłową liczbę\n");
  42. while (getchar() != '\n');
  43. }
  44.  
  45. return number;
  46. }
  47.  
  48.  
  49. double ReadDouble(const char* message)
  50. {
  51. double number;
  52.  
  53. while (1) //petla wykonuje sie dopoki uzytkownik nie poda wlasciwej wartosci liczbowej (double)
  54. {
  55. printf(message);
  56.  
  57. if (scanf("%lf", &number) == 1)
  58. {
  59. break;
  60. }
  61.  
  62. printf("Podano nieprawidłową liczbę\n");
  63. while (getchar() != '\n');
  64. }
  65.  
  66. return number;
  67. }
  68.  
  69. const char* ReadText(const char* message)
  70. {
  71. static char buffer[4096]; // zmienna statyczna, jest odpowiednikiem zmiennej globalnej, ale ma zasięg lokalny w funkcji ReadText
  72. printf(message);
  73. scanf("%s", buffer); // odczytuje to, co uzytkownik wpisal i na koncu umieszcza 0 (terminator)
  74. return buffer;
  75. }
  76.  
  77. const char* ReadPath(const char* message, const char* extension) //funkcja dodaje odpowiednie rozszerzenie
  78. {
  79. char* path;
  80. path = ReadText(message);
  81. if (strstr(path, extension) == NULL) //sprawdzenie, czy dodaliśmy ręcznie rozszerzenie
  82. {
  83. strcat(path, extension); // jeśli nie, to funkcja dodaje rozszerzenie
  84. }
  85. return path;
  86. }
  87.  
  88. int ScanInteger(FILE* file, int* result) //funkcja sprawdzająca, czy w pliku są komentarze
  89. {
  90. int c;
  91. while (1)
  92. {
  93. if (fscanf(file, "%d", result) == 1)
  94. {
  95. return 1;
  96. }
  97. if (fgetc(file) == '#')
  98. {
  99. while (1) //gdy mamy wartość true, to pomijamy komentarz
  100. {
  101. c = fgetc(file);
  102. if (c == EOF || c == '\n')
  103. {
  104. break;
  105. }
  106.  
  107. }
  108.  
  109. }
  110. else
  111. {
  112. break;
  113. }
  114. }
  115. return 0;
  116. }
  117.  
  118. void AlocatePixels(PgmImage* image)
  119. {
  120. int i;
  121.  
  122. image->pixels = malloc(image->width * sizeof(unsigned short*)); // tworzymy tablicę wskaźników
  123. for (i = 0; i < image->width; i++)
  124. {
  125. image->pixels[i] = malloc(image->height * sizeof(unsigned short)); // tworzymy konkretne komórki
  126. }
  127. }
  128.  
  129. void FreePixels(PgmImage* image) //najpierw zwalniamy tablicę zmiennych, potem zwalniamy tablicę adresów
  130. {
  131. int i;
  132. for (i = 0; i < image->width; i++)
  133. {
  134. free(image->pixels[i]);
  135. }
  136. free(image->pixels);
  137. }
  138.  
  139. int ReadPgm(const char* path, PgmImage* image)
  140. {
  141. FILE* file;
  142. int x, y, pixel;
  143.  
  144. file = fopen(path, "rb");
  145. if (file != NULL)
  146. {
  147. if (fgetc(file) == 'P' && fgetc(file) == '2') //sprawdzenie czy mamy nagłówek P2
  148. {
  149. if (ScanInteger(file, &image->width) &&
  150. ScanInteger(file, &image->height) &&
  151. ScanInteger(file, &image->depth))
  152. {
  153. AlocatePixels(image);
  154. for (y = 0; y < image->height; y++)
  155. {
  156. for (x = 0; x < image->width; x++)
  157. {
  158. if (!ScanInteger(file, &pixel))
  159. {
  160. FreePixels(image);
  161. return 0; //nie udało się odczytać wartości pixela
  162. }
  163. image->pixels[x][y] = pixel;
  164. }
  165. }
  166. return 1; //udało się odczytać obraz
  167. }
  168. }
  169.  
  170. fclose(file);
  171. }
  172. return 0;
  173. }
  174.  
  175. int SavePgm(const char* path, PgmImage* image)
  176. {
  177. FILE* file;
  178. int x, y;
  179.  
  180. file = fopen(path, "wb");
  181. if (file != NULL)
  182. {
  183. fprintf(file, "P2\n");
  184. fprintf(file, "%d %d\n", image->width, image->height);
  185. fprintf(file, "%d\n", image->depth);
  186.  
  187. for (y = 0; y < image->height; y++)
  188. {
  189. for (x = 0; x < image->width; x++)
  190. {
  191. fprintf(file, "%d\n", image->pixels[x][y]);
  192. }
  193. }
  194. fclose(file);
  195. return 1;
  196. }
  197.  
  198. return 0;
  199. }
  200.  
  201. void DbInitialize(PgmImageDb* db) //funkcja inicjalizująca bazę obrazów
  202. {
  203. db->images = NULL;
  204. db->length = 0;
  205. db->index = -1; // nie jesteśmy na żadnym indeksie, czyli nie mamy żadnego obrazu, dlatego -1
  206. }
  207.  
  208. void DbFree(PgmImageDb* db) //funkcja zwalniająca bazę obrazów
  209. {
  210. int i;
  211. for (i = 0; i < db->length; i++)
  212. {
  213. FreePixels(&db->images[i]);
  214. }
  215. }
  216.  
  217. void DbAdd(PgmImageDb* db, PgmImage* image)
  218. {
  219. db->length++;
  220. db->images = realloc(db->images, (db->length) * sizeof(PgmImage));
  221. db->images[db->length - 1] = *image;
  222. if (db->length == 1)
  223. {
  224. db->index = 0; //po dodaniu pierwszego obrazka ustawiamy go jako aktywny
  225. }
  226. }
  227.  
  228. int DbRemove(PgmImageDb* db, int index)
  229. {
  230. if (index >= 0 && index < db->length)
  231. {
  232. db->length--;
  233. FreePixels(&db->images[db->length]); //zwalniamy pixele dla ostatniego obrazu w tablicy
  234. db->images = realloc(db->images, (db->length) * sizeof(PgmImage));
  235. if (db->index == index)
  236. {
  237. db->index = -1;
  238. }
  239. return 1;
  240. }
  241. return 0;
  242. }
  243.  
  244. void DbPrint(PgmImageDb* db)
  245. {
  246. int i;
  247. PgmImage* image;
  248. for (i = 0; i < db->length; i++)
  249. {
  250. image = &db->images[i];
  251. printf("Obraz o indeksie %d (%dx%dx%d)\n", i, image->width, image->height, image->depth);
  252. }
  253. printf("Aktywny indeks = %d\n", db->index);
  254. }
  255.  
  256. int DbChangeIndex(PgmImageDb* db, int index)
  257. {
  258. if (index >=0 && index < db->length)
  259. {
  260. db->index = index;
  261. return 1;
  262. }
  263. return 0;
  264. }
  265.  
  266. double Random()
  267. {
  268. return (double)rand() / RAND_MAX; // wartość od 0 do 1, zmiennoprzecinkowa
  269. }
  270.  
  271. void Noise(PgmImage* image)
  272. {
  273. int x, y;
  274. for (y = 0; y < image->height; y++)
  275. {
  276. for (x = 0; x < image->width; x++)
  277. {
  278.  
  279. if (Random() <= 0.1)
  280. {
  281. if (Random() >= 0.5)
  282. {
  283. image->pixels[x][y] = 0; // piksel stanie się czarny
  284. }
  285. else
  286. {
  287. image->pixels[x][y] = image->depth; // piksel stanie się biały
  288. }
  289. }
  290. }
  291. }
  292. }
  293.  
  294. int* CreateHistogram(PgmImage* image)
  295. {
  296. int* histogram;
  297. int x, y;
  298. unsigned short pixel;
  299.  
  300. histogram = calloc(image->depth+1, sizeof(int));
  301. // image->depth+1 - potrzebujemy mieć zawsze jedną komórkę więcej niż wartość głębii obrazu
  302.  
  303. for (y = 0; y < image->height; y++)
  304. {
  305. for (x = 0; x < image->width; x++)
  306. {
  307. pixel = image->pixels[x][y];
  308. histogram[pixel] = histogram[pixel] + 1;
  309. }
  310. }
  311. return histogram;
  312. }
  313.  
  314. void SaveHistogram(const char* path, int* histogram, int length)
  315. {
  316. FILE* file;
  317. int i;
  318.  
  319. file = fopen(path, "wb");
  320. if (file != NULL)
  321. {
  322. for (i = 0; i < length; i++)
  323. {
  324. fprintf(file, "%d;%d\n", i, histogram[i]);
  325. // i to wartość piksela (szarości), histogram [i] to ilość wystąpień tej wartości w obrazie
  326. }
  327. fclose(file);
  328. }
  329.  
  330. }
  331.  
  332. int Compare(const void* x, const void* y)
  333. // jeżeli zwrócona wartość z Compare jest dodatnia
  334. // to qsort przestawia elementy tablicy
  335. // w przeciwnym wypadku zostawia je tak jak było (czy mamy zero, czy wartość ujemną)
  336. {
  337. unsigned short i, j;
  338.  
  339. i = *(unsigned short*)x; // rzutowanie na odpowiedni typ wskaźnika
  340. j = *(unsigned short*)y;
  341.  
  342. return (int)i-(int)j;
  343.  
  344. }
  345.  
  346. unsigned short Median(unsigned short* pixels)
  347. {
  348. qsort(pixels, 9, sizeof(unsigned short), Compare);
  349. return pixels[4]; //środkowa wartość
  350. }
  351.  
  352.  
  353. void MedianFilter(PgmImage* image)
  354. {
  355. int x, y;
  356. unsigned short pixels[9];
  357. for (y = 0; y < image->height - 2; y++)
  358. {
  359. for (x = 0; x < image->width - 2; x++)
  360. {
  361. // 1 2 3
  362. // 4 5 6
  363. // 7 8 9
  364. pixels[0] = image->pixels[x][y]; //1
  365. pixels[1] = image->pixels[x+1][y]; //2
  366. pixels[2] = image->pixels[x+2][y]; //3
  367. pixels[3] = image->pixels[x][y+1]; //4
  368. pixels[4] = image->pixels[x+1][y+1]; //5
  369. pixels[5] = image->pixels[x+2][y+1]; //6
  370. pixels[6] = image->pixels[x][y+2]; //7
  371. pixels[7] = image->pixels[x+1][y+2]; //8
  372. pixels[8] = image->pixels[x+2][y+2]; //9
  373.  
  374. image->pixels[x + 1][y + 1] = Median(pixels);
  375. }
  376. }
  377. }
  378.  
  379. void Negative(PgmImage* image)
  380. {
  381. int x, y;
  382. unsigned short pixel;
  383. for (y = 0; y < image->height; y++)
  384. {
  385. for (x = 0; x < image->width; x++)
  386. {
  387. pixel = image->depth - image->pixels[x][y];
  388. image->pixels[x][y] = pixel;
  389. }
  390. }
  391. }
  392.  
  393. void Rotate90(PgmImage* image)
  394. {
  395. int x, y;
  396. PgmImage temp;
  397. temp.width = image->height;
  398. temp.height = image->width;
  399. AlocatePixels(&temp);
  400. for (y = 0; y < image->height; y++)
  401. {
  402. for (x = 0; x < image->width; x++)
  403. {
  404. temp.pixels[y][x] = image->pixels[x][y];
  405. }
  406. }
  407. FreePixels(image); //zwalniamy pamięć oryginalnego obrazu
  408. image->width = temp.width;
  409. image->height = temp.height;
  410. image->pixels = temp.pixels; //wskaźnik (adres obszaru pamięci)
  411. }
  412.  
  413. void Rotate90k(PgmImage* image, int k)
  414. {
  415. int i;
  416. if (k < 0)
  417. {
  418. k = -k;
  419. }
  420. for (i = 0; i < k; i++)
  421. {
  422. Rotate90(image);
  423. }
  424. }
  425.  
  426. int main()
  427. {
  428. int finish, n, index, k;
  429. PgmImage image;
  430. PgmImageDb db;
  431. const char* path;
  432. int* histogram;
  433.  
  434. system("chcp 1250 > nul"); // odczytywanie polskich znaków w konsoli
  435.  
  436. srand(time(NULL));
  437.  
  438. finish = 0;
  439.  
  440. DbInitialize(&db);
  441.  
  442. while (!finish)
  443. {
  444. printf("1. Wczytaj (dodaj) plik PGM do bazy obrazów\n");
  445. printf("2. Zapisz aktywny plik PGM\n");
  446. printf("3. Usuń obraz z bazy obrazów\n");
  447. printf("4. Wyświetl szczegóły bazy obrazów\n");
  448. printf("5. Wybierz aktywny plik PGM z bazy obrazów\n");
  449. printf("6. Obróć aktywny plik PGM o 90*k stopni\n");
  450. printf("7. Zapisz histogram aktywnego pliku PGM do pliku CSV\n");
  451. printf("8. Zastosuj negatyw do aktywnego pliku PGM\n");
  452. printf("9. Zaszum aktywny plik PGM (pieprz/sól)\n");
  453. printf("10. Zastosuj filtr medianowy do aktywnego pliku PGM\n");
  454. printf("0. Koniec programu\n");
  455. n = ReadInteger("");
  456. switch (n)
  457. {
  458. case 1:
  459. path = ReadPath("Podaj ścieżkę do pliku\n", ".pgm");
  460. if (ReadPgm(path, &image) == 0)
  461. {
  462. printf("Nie udało się wczytać pliku\n");
  463. }
  464. else
  465. {
  466. DbAdd(&db, &image);
  467. }
  468. break;
  469.  
  470. case 2:
  471. if (db.index != -1)
  472. {
  473. path = ReadPath("Podaj ścieżkę do pliku\n", ".pgm");
  474. if (SavePgm(path, &db.images[db.index]) == 0)
  475. {
  476. printf("Nie udało się zapisać pliku\n");
  477. }
  478. }
  479. else
  480. {
  481. printf("Wybierz aktywny plik PGM z bazy obrazów\n");
  482. }
  483. break;
  484.  
  485. case 3:
  486. index = ReadInteger("Podaj indeks obrazu, który chcesz usunąć: ");
  487. if (!DbRemove(&db, index))
  488. {
  489. printf("Podano nieprawidłowy indeks\n");
  490. }
  491. break;
  492.  
  493. case 4:
  494. DbPrint(&db);
  495. break;
  496.  
  497. case 5:
  498. index = ReadInteger("Podaj indeks obrazu, który ma być aktywny: ");
  499. if (!DbChangeIndex(&db, index))
  500. {
  501. printf("Podano indeks z nieprawidłowego zakresu\n");
  502. }
  503. break;
  504.  
  505. case 6:
  506. if (db.index != -1)
  507. {
  508. k = ReadInteger("Podaj parametr k: ");
  509. Rotate90k(&db.images[db.index], k);
  510. }
  511. else
  512. {
  513. printf("Wybierz aktywny plik PGM z bazy obrazów\n");
  514. }
  515. break;
  516.  
  517. case 7:
  518. if (db.index != -1)
  519. {
  520. path = ReadPath("Podaj ścieżkę do pliku: ", ".csv");
  521. histogram = CreateHistogram(&db.images[db.index]); // wskaźnik do aktywnego obrazka (domyślnie o indeksie 0)
  522. SaveHistogram(path, histogram, db.images[db.index].depth+1);
  523. free(histogram);
  524. }
  525. else
  526. {
  527. printf("Wybierz aktywny plik PGM z bazy obrazów\n");
  528. }
  529. break;
  530.  
  531. case 8:
  532. if (db.index != -1)
  533. {
  534. Negative(&db.images[db.index]);
  535. }
  536. else
  537. {
  538. printf("Wybierz aktywny plik PGM z bazy obrazów\n");
  539. }
  540. break;
  541.  
  542. case 9:
  543. if (db.index != -1)
  544. {
  545. Noise(&db.images[db.index]);
  546. }
  547. else
  548. {
  549. printf("Wybierz aktywny plik PGM z bazy obrazów\n");
  550. }
  551. break;
  552.  
  553. case 10:
  554. if (db.index != -1)
  555. {
  556. MedianFilter(&db.images[db.index]); // wskaźnik do aktywnego obrazka (domyślnie o indeksie 0)
  557. }
  558. else
  559. {
  560. printf("Wybierz aktywny plik PGM z bazy obrazów\n");
  561. }
  562. break;
  563.  
  564. case 0:
  565. finish = 1;
  566. break;
  567.  
  568. default:
  569. printf("Podano błędną wartość\n");
  570. }
  571. }
  572. DbFree(&db);
  573.  
  574.  
  575. return 0;
  576. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement