SHARE
TWEET

Untitled

a guest Dec 16th, 2019 62 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top