Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <string.h>
- struct PgmImage
- {
- int width;
- int height;
- unsigned short depth; //głębia szarości
- unsigned short** pixels; //tablica wskaźników (macierz pixeli)
- };
- typedef struct PgmImage PgmImage; // typedef - zamienia struct pgmimage na pgmimage
- struct PgmImageDb
- {
- PgmImage* images;
- int length;
- int index; //aktywny indeks
- };
- typedef struct PgmImageDb PgmImageDb;
- int ReadInteger(const char* message)
- {
- int number;
- while (1) //petla wykonuje sie dopoki uzytkownik nie poda wlasciwej wartosci liczbowej (int)
- {
- printf(message);
- if (scanf("%d", &number) == 1)
- {
- break;
- }
- printf("Podano nieprawidłową liczbę\n");
- while (getchar() != '\n');
- }
- return number;
- }
- double ReadDouble(const char* message)
- {
- double number;
- while (1) //petla wykonuje sie dopoki uzytkownik nie poda wlasciwej wartosci liczbowej (double)
- {
- printf(message);
- if (scanf("%lf", &number) == 1)
- {
- break;
- }
- printf("Podano nieprawidłową liczbę\n");
- while (getchar() != '\n');
- }
- return number;
- }
- const char* ReadText(const char* message)
- {
- static char buffer[4096]; // zmienna statyczna, jest odpowiednikiem zmiennej globalnej, ale ma zasięg lokalny w funkcji ReadText
- printf(message);
- scanf("%s", buffer); // odczytuje to, co uzytkownik wpisal i na koncu umieszcza 0 (terminator)
- return buffer;
- }
- const char* ReadPath(const char* message, const char* extension) //funkcja dodaje odpowiednie rozszerzenie
- {
- char* path;
- path = ReadText(message);
- if (strstr(path, extension) == NULL) //sprawdzenie, czy dodaliśmy ręcznie rozszerzenie
- {
- strcat(path, extension); // jeśli nie, to funkcja dodaje rozszerzenie
- }
- return path;
- }
- int ScanInteger(FILE* file, int* result) //funkcja sprawdzająca, czy w pliku są komentarze
- {
- int c;
- while (1)
- {
- if (fscanf(file, "%d", result) == 1)
- {
- return 1;
- }
- if (fgetc(file) == '#')
- {
- while (1) //gdy mamy wartość true, to pomijamy komentarz
- {
- c = fgetc(file);
- if (c == EOF || c == '\n')
- {
- break;
- }
- }
- }
- else
- {
- break;
- }
- }
- return 0;
- }
- void AlocatePixels(PgmImage* image)
- {
- int i;
- image->pixels = malloc(image->width * sizeof(unsigned short*)); // tworzymy tablicę wskaźników
- for (i = 0; i < image->width; i++)
- {
- image->pixels[i] = malloc(image->height * sizeof(unsigned short)); // tworzymy konkretne komórki
- }
- }
- void FreePixels(PgmImage* image) //najpierw zwalniamy tablicę zmiennych, potem zwalniamy tablicę adresów
- {
- int i;
- for (i = 0; i < image->width; i++)
- {
- free(image->pixels[i]);
- }
- free(image->pixels);
- }
- int ReadPgm(const char* path, PgmImage* image)
- {
- FILE* file;
- int x, y, pixel;
- file = fopen(path, "rb");
- if (file != NULL)
- {
- if (fgetc(file) == 'P' && fgetc(file) == '2') //sprawdzenie czy mamy nagłówek P2
- {
- if (ScanInteger(file, &image->width) &&
- ScanInteger(file, &image->height) &&
- ScanInteger(file, &image->depth))
- {
- AlocatePixels(image);
- for (y = 0; y < image->height; y++)
- {
- for (x = 0; x < image->width; x++)
- {
- if (!ScanInteger(file, &pixel))
- {
- FreePixels(image);
- return 0; //nie udało się odczytać wartości pixela
- }
- image->pixels[x][y] = pixel;
- }
- }
- return 1; //udało się odczytać obraz
- }
- }
- fclose(file);
- }
- return 0;
- }
- int SavePgm(const char* path, PgmImage* image)
- {
- FILE* file;
- int x, y;
- file = fopen(path, "wb");
- if (file != NULL)
- {
- fprintf(file, "P2\n");
- fprintf(file, "%d %d\n", image->width, image->height);
- fprintf(file, "%d\n", image->depth);
- for (y = 0; y < image->height; y++)
- {
- for (x = 0; x < image->width; x++)
- {
- fprintf(file, "%d\n", image->pixels[x][y]);
- }
- }
- fclose(file);
- return 1;
- }
- return 0;
- }
- void DbInitialize(PgmImageDb* db) //funkcja inicjalizująca bazę obrazów
- {
- db->images = NULL;
- db->length = 0;
- db->index = -1; // nie jesteśmy na żadnym indeksie, czyli nie mamy żadnego obrazu, dlatego -1
- }
- void DbFree(PgmImageDb* db) //funkcja zwalniająca bazę obrazów
- {
- int i;
- for (i = 0; i < db->length; i++)
- {
- FreePixels(&db->images[i]);
- }
- }
- void DbAdd(PgmImageDb* db, PgmImage* image)
- {
- db->length++;
- db->images = realloc(db->images, (db->length) * sizeof(PgmImage));
- db->images[db->length - 1] = *image;
- if (db->length == 1)
- {
- db->index = 0; //po dodaniu pierwszego obrazka ustawiamy go jako aktywny
- }
- }
- int DbRemove(PgmImageDb* db, int index)
- {
- if (index >= 0 && index < db->length)
- {
- db->length--;
- FreePixels(&db->images[db->length]); //zwalniamy pixele dla ostatniego obrazu w tablicy
- db->images = realloc(db->images, (db->length) * sizeof(PgmImage));
- if (db->index == index)
- {
- db->index = -1;
- }
- return 1;
- }
- return 0;
- }
- void DbPrint(PgmImageDb* db)
- {
- int i;
- PgmImage* image;
- for (i = 0; i < db->length; i++)
- {
- image = &db->images[i];
- printf("Obraz o indeksie %d (%dx%dx%d)\n", i, image->width, image->height, image->depth);
- }
- printf("Aktywny indeks = %d\n", db->index);
- }
- int DbChangeIndex(PgmImageDb* db, int index)
- {
- if (index >=0 && index < db->length)
- {
- db->index = index;
- return 1;
- }
- return 0;
- }
- double Random()
- {
- return (double)rand() / RAND_MAX; // wartość od 0 do 1, zmiennoprzecinkowa
- }
- void Noise(PgmImage* image)
- {
- int x, y;
- for (y = 0; y < image->height; y++)
- {
- for (x = 0; x < image->width; x++)
- {
- if (Random() <= 0.1)
- {
- if (Random() >= 0.5)
- {
- image->pixels[x][y] = 0; // piksel stanie się czarny
- }
- else
- {
- image->pixels[x][y] = image->depth; // piksel stanie się biały
- }
- }
- }
- }
- }
- int* CreateHistogram(PgmImage* image)
- {
- int* histogram;
- int x, y;
- unsigned short pixel;
- histogram = calloc(image->depth+1, sizeof(int));
- // image->depth+1 - potrzebujemy mieć zawsze jedną komórkę więcej niż wartość głębii obrazu
- for (y = 0; y < image->height; y++)
- {
- for (x = 0; x < image->width; x++)
- {
- pixel = image->pixels[x][y];
- histogram[pixel] = histogram[pixel] + 1;
- }
- }
- return histogram;
- }
- void SaveHistogram(const char* path, int* histogram, int length)
- {
- FILE* file;
- int i;
- file = fopen(path, "wb");
- if (file != NULL)
- {
- for (i = 0; i < length; i++)
- {
- fprintf(file, "%d;%d\n", i, histogram[i]);
- // i to wartość piksela (szarości), histogram [i] to ilość wystąpień tej wartości w obrazie
- }
- fclose(file);
- }
- }
- int Compare(const void* x, const void* y)
- // jeżeli zwrócona wartość z Compare jest dodatnia
- // to qsort przestawia elementy tablicy
- // w przeciwnym wypadku zostawia je tak jak było (czy mamy zero, czy wartość ujemną)
- {
- unsigned short i, j;
- i = *(unsigned short*)x; // rzutowanie na odpowiedni typ wskaźnika
- j = *(unsigned short*)y;
- return (int)i-(int)j;
- }
- unsigned short Median(unsigned short* pixels)
- {
- qsort(pixels, 9, sizeof(unsigned short), Compare);
- return pixels[4]; //środkowa wartość
- }
- void MedianFilter(PgmImage* image)
- {
- int x, y;
- unsigned short pixels[9];
- for (y = 0; y < image->height - 2; y++)
- {
- for (x = 0; x < image->width - 2; x++)
- {
- // 1 2 3
- // 4 5 6
- // 7 8 9
- pixels[0] = image->pixels[x][y]; //1
- pixels[1] = image->pixels[x+1][y]; //2
- pixels[2] = image->pixels[x+2][y]; //3
- pixels[3] = image->pixels[x][y+1]; //4
- pixels[4] = image->pixels[x+1][y+1]; //5
- pixels[5] = image->pixels[x+2][y+1]; //6
- pixels[6] = image->pixels[x][y+2]; //7
- pixels[7] = image->pixels[x+1][y+2]; //8
- pixels[8] = image->pixels[x+2][y+2]; //9
- image->pixels[x + 1][y + 1] = Median(pixels);
- }
- }
- }
- void Negative(PgmImage* image)
- {
- int x, y;
- unsigned short pixel;
- for (y = 0; y < image->height; y++)
- {
- for (x = 0; x < image->width; x++)
- {
- pixel = image->depth - image->pixels[x][y];
- image->pixels[x][y] = pixel;
- }
- }
- }
- void Rotate90(PgmImage* image)
- {
- int x, y;
- PgmImage temp;
- temp.width = image->height;
- temp.height = image->width;
- AlocatePixels(&temp);
- for (y = 0; y < image->height; y++)
- {
- for (x = 0; x < image->width; x++)
- {
- temp.pixels[y][x] = image->pixels[x][y];
- }
- }
- FreePixels(image); //zwalniamy pamięć oryginalnego obrazu
- image->width = temp.width;
- image->height = temp.height;
- image->pixels = temp.pixels; //wskaźnik (adres obszaru pamięci)
- }
- void Rotate90k(PgmImage* image, int k)
- {
- int i;
- if (k < 0)
- {
- k = -k;
- }
- for (i = 0; i < k; i++)
- {
- Rotate90(image);
- }
- }
- int main()
- {
- int finish, n, index, k;
- PgmImage image;
- PgmImageDb db;
- const char* path;
- int* histogram;
- system("chcp 1250 > nul"); // odczytywanie polskich znaków w konsoli
- srand(time(NULL));
- finish = 0;
- DbInitialize(&db);
- while (!finish)
- {
- printf("1. Wczytaj (dodaj) plik PGM do bazy obrazów\n");
- printf("2. Zapisz aktywny plik PGM\n");
- printf("3. Usuń obraz z bazy obrazów\n");
- printf("4. Wyświetl szczegóły bazy obrazów\n");
- printf("5. Wybierz aktywny plik PGM z bazy obrazów\n");
- printf("6. Obróć aktywny plik PGM o 90*k stopni\n");
- printf("7. Zapisz histogram aktywnego pliku PGM do pliku CSV\n");
- printf("8. Zastosuj negatyw do aktywnego pliku PGM\n");
- printf("9. Zaszum aktywny plik PGM (pieprz/sól)\n");
- printf("10. Zastosuj filtr medianowy do aktywnego pliku PGM\n");
- printf("0. Koniec programu\n");
- n = ReadInteger("");
- switch (n)
- {
- case 1:
- path = ReadPath("Podaj ścieżkę do pliku\n", ".pgm");
- if (ReadPgm(path, &image) == 0)
- {
- printf("Nie udało się wczytać pliku\n");
- }
- else
- {
- DbAdd(&db, &image);
- }
- break;
- case 2:
- if (db.index != -1)
- {
- path = ReadPath("Podaj ścieżkę do pliku\n", ".pgm");
- if (SavePgm(path, &db.images[db.index]) == 0)
- {
- printf("Nie udało się zapisać pliku\n");
- }
- }
- else
- {
- printf("Wybierz aktywny plik PGM z bazy obrazów\n");
- }
- break;
- case 3:
- index = ReadInteger("Podaj indeks obrazu, który chcesz usunąć: ");
- if (!DbRemove(&db, index))
- {
- printf("Podano nieprawidłowy indeks\n");
- }
- break;
- case 4:
- DbPrint(&db);
- break;
- case 5:
- index = ReadInteger("Podaj indeks obrazu, który ma być aktywny: ");
- if (!DbChangeIndex(&db, index))
- {
- printf("Podano indeks z nieprawidłowego zakresu\n");
- }
- break;
- case 6:
- if (db.index != -1)
- {
- k = ReadInteger("Podaj parametr k: ");
- Rotate90k(&db.images[db.index], k);
- }
- else
- {
- printf("Wybierz aktywny plik PGM z bazy obrazów\n");
- }
- break;
- case 7:
- if (db.index != -1)
- {
- path = ReadPath("Podaj ścieżkę do pliku: ", ".csv");
- histogram = CreateHistogram(&db.images[db.index]); // wskaźnik do aktywnego obrazka (domyślnie o indeksie 0)
- SaveHistogram(path, histogram, db.images[db.index].depth+1);
- free(histogram);
- }
- else
- {
- printf("Wybierz aktywny plik PGM z bazy obrazów\n");
- }
- break;
- case 8:
- if (db.index != -1)
- {
- Negative(&db.images[db.index]);
- }
- else
- {
- printf("Wybierz aktywny plik PGM z bazy obrazów\n");
- }
- break;
- case 9:
- if (db.index != -1)
- {
- Noise(&db.images[db.index]);
- }
- else
- {
- printf("Wybierz aktywny plik PGM z bazy obrazów\n");
- }
- break;
- case 10:
- if (db.index != -1)
- {
- MedianFilter(&db.images[db.index]); // wskaźnik do aktywnego obrazka (domyślnie o indeksie 0)
- }
- else
- {
- printf("Wybierz aktywny plik PGM z bazy obrazów\n");
- }
- break;
- case 0:
- finish = 1;
- break;
- default:
- printf("Podano błędną wartość\n");
- }
- }
- DbFree(&db);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement