Kopiuj
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct Obraz {
char nazwa[100];
int szerokosc;
int wysokosc;
int glebi;
int** piksele;
};
struct Obraz obrazy[100];
int liczbaObrazow = 0;
int** alokujTablice2D(int szerokosc, int wysokosc) {
int** tablica = (int**)malloc(wysokosc * sizeof(int*));
if (!tablica) {
printf("Blad alokacji pamieci dla tablicy 2D\n");
return NULL;
}
for (int i = 0; i < wysokosc; i++) {
tablica[i] = (int*)malloc(szerokosc * sizeof(int));
if (!tablica[i]) {
printf("Blad alokacji pamieci dla wiersza tablicy 2D\n");
for (int j = 0; j < i; j++) {
free(tablica[j]);
}
free(tablica);
return NULL;
}
}
return tablica;
}
void zwolnijTablice2D(int** tablica, int wysokosc) {
if (tablica) {
for (int i = 0; i < wysokosc; i++) {
free(tablica[i]);
}
free(tablica);
}
}
int czyPoprawneRozszerzenie(const char* nazwaPliku) {
size_t dlugosc = strlen(nazwaPliku);
if (dlugosc < 4) {
printf("Nazwa pliku jest za krotka, aby zawierac rozszerzenie .pgm\n");
return 0;
}
if (strcmp(&nazwaPliku[dlugosc - 4], ".pgm") == 0) {
return 1;
}
printf("Plik nie ma poprawnego rozszerzenia .pgm\n");
return 0;
}
int odczytajPGM(struct Obraz* obraz, char* nazwaPliku) {
if (!czyPoprawneRozszerzenie(nazwaPliku)) {
return 0;
}
FILE* plik = fopen(nazwaPliku, "r");
if (!plik) {
printf("Nie udalo sie otworzyc pliku %s\n", nazwaPliku);
return 0;
}
fscanf(plik, "P2");
fscanf(plik, "%d %d", &obraz->szerokosc, &obraz->wysokosc);
fscanf(plik, "%d", &obraz->glebi);
obraz->piksele = alokujTablice2D(obraz->szerokosc, obraz->wysokosc);
if (!obraz->piksele) {
fclose(plik);
return 0;
}
for (int i = 0; i < obraz->wysokosc; i++) {
for (int j = 0; j < obraz->szerokosc; j++) {
fscanf(plik, "%d", &obraz->piksele[i][j]);
}
}
fclose(plik);
return 1;
}
int zapiszPGM(struct Obraz* obraz, char* nazwaPliku) {
FILE* plik = fopen(nazwaPliku, "w");
if (!plik) {
printf("Nie udalo sie otworzyc pliku do zapisu\n");
return 0;
}
fprintf(plik, "P2\n%d %d\n%d\n", obraz->szerokosc, obraz->wysokosc, obraz->glebi);
for (int i = 0; i < obraz->wysokosc; i++) {
for (int j = 0; j < obraz->szerokosc; j++) {
fprintf(plik, "%d ", obraz->piksele[i][j]);
}
fprintf(plik, "\n");
}
fclose(plik);
return 1;
}
void histogramDoCSV(struct Obraz* obraz, const char* nazwaCSV) {
int* histogram = (int*)calloc(obraz->glebi + 1, sizeof(int));
if (!histogram) {
printf("Blad alokacji pamieci dla histogramu\n");
return;
}
for (int i = 0; i < obraz->wysokosc; i++) {
for (int j = 0; j < obraz->szerokosc; j++) {
histogram[obraz->piksele[i][j]]++;
}
}
FILE* plik = fopen(nazwaCSV, "w");
if (!plik) {
printf("Nie udalo sie otworzyc pliku do zapisu histogramu\n");
free(histogram);
return;
}
fprintf(plik, "Jasnosc,Ilosc\n");
for (int i = 0; i <= obraz->glebi; i++) {
fprintf(plik, "%d,%d\n", i, histogram[i]);
}
fclose(plik);
free(histogram);
printf("Histogram zapisany do pliku %s\n", nazwaCSV);
}
void negatyw(struct Obraz* obraz) {
for (int i = 0; i < obraz->wysokosc; i++) {
for (int j = 0; j < obraz->szerokosc; j++) {
obraz->piksele[i][j] = obraz->glebi - obraz->piksele[i][j];
}
}
printf("Negatyw wykonany.\n");
}
void obroc90(struct Obraz* obraz) {
int** obrocony = alokujTablice2D(obraz->wysokosc, obraz->szerokosc);
if (!obrocony) {
printf("Blad alokacji pamieci.\n");
return;
}
for (int i = 0; i < obraz->wysokosc; i++) {
for (int j = 0; j < obraz->szerokosc; j++) {
obrocony[j][obraz->wysokosc - i - 1] = obraz->piksele[i][j];
}
}
zwolnijTablice2D(obraz->piksele, obraz->wysokosc);
obraz->piksele = obrocony;
int temp = obraz->szerokosc;
obraz->szerokosc = obraz->wysokosc;
obraz->wysokosc = temp;
printf("Obrot o 90 stopni wykonano.\n");
}
void zaszumObraz(struct Obraz* obraz, float poziom) {
int liczbaZakloconych = (int)(poziom * obraz->szerokosc * obraz->wysokosc);
srand(time(NULL));
for (int k = 0; k < liczbaZakloconych; k++) {
int i = rand() % obraz->wysokosc;
int j = rand() % obraz->szerokosc;
obraz->piksele[i][j] = (rand() % 2 == 0) ? 0 : obraz->glebi;
}
printf("Obraz zaszumiono.\n");
}
void filtrMedianowy(struct Obraz* obraz) {
int** nowaTablica = alokujTablice2D(obraz->szerokosc, obraz->wysokosc);
if (!nowaTablica) {
printf("Blad alokacji pamieci.\n");
return;
}
int okno[9];
for (int y = 1; y < obraz->wysokosc - 1; y++) {
for (int x = 1; x < obraz->szerokosc - 1; x++) {
int k = 0;
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
okno[k++] = obraz->piksele[y + dy][x + dx];
}
}
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8 - i; j++) {
if (okno[j] > okno[j + 1]) {
int temp = okno[j];
okno[j] = okno[j + 1];
okno[j + 1] = temp;
}
}
}
nowaTablica[y][x] = okno[4];
}
}
zwolnijTablice2D(obraz->piksele, obraz->wysokosc);
obraz->piksele = nowaTablica;
printf("Filtr medianowy wykonano.\n");
}
void wyswietlListeObrazow() {
if (liczbaObrazow == 0) {
printf("Brak obrazow.\n");
}
else {
for (int i = 0; i < liczbaObrazow; i++) {
printf("%d. %s (%dx%d, glebi: %d)\n", i, obrazy[i].nazwa, obrazy[i].szerokosc, obrazy[i].wysokosc, obrazy[i].glebi);
}
}
}
void usunObraz(int indeks) {
if (indeks < 0 || indeks >= liczbaObrazow) {
printf("Niepoprawny indeks obrazu\n");
return;
}
zwolnijTablice2D(obrazy[indeks].piksele, obrazy[indeks].wysokosc);
for (int i = indeks; i < liczbaObrazow - 1; i++) {
obrazy[i] = obrazy[i + 1];
}
liczbaObrazow--;
printf("Obraz usuniety\n");
}
int main() {
int opcja;
char nazwaPliku[100];
while (1) {
printf("\nMENU:\n");
printf("1. Wczytaj obraz\n");
printf("2. Zapisz obraz\n");
printf("3. Negatyw obrazu\n");
printf("4. Obrot o 90 stopni\n");
printf("5. Szum pieprz i sol\n");
printf("6. Filtr medianowy\n");
printf("7. Histogram do CSV\n");
printf("8. Wyswietl liste obrazow\n");
printf("9. Usun obraz\n");
printf("0. Wyjdz\n");
printf("Wybierz opcje: ");
scanf("%d", &opcja);
if (opcja == 0) break;
int indeks;
switch (opcja) {
case 1:
if (liczbaObrazow < 100) {
printf("Podaj nazwe pliku: ");
scanf("%s", nazwaPliku);
if (odczytajPGM(&obrazy[liczbaObrazow], nazwaPliku)) {
strcpy(obrazy[liczbaObrazow].nazwa, nazwaPliku);
liczbaObrazow++;
}
}
else {
printf("Osiagnieto limit obrazow.\n");
}
break;
case 2:
printf("Podaj indeks obrazu: ");
scanf("%d", &indeks);
if (indeks >= 0 && indeks < liczbaObrazow) {
printf("Podaj nazwe pliku: ");
scanf("%s", nazwaPliku);
zapiszPGM(&obrazy[indeks], nazwaPliku);
}
break;
case 3:
printf("Podaj indeks obrazu: ");
scanf("%d", &indeks);
if (indeks >= 0 && indeks < liczbaObrazow) {
negatyw(&obrazy[indeks]);
}
break;
case 4:
printf("Podaj indeks obrazu: ");
scanf("%d", &indeks);
if (indeks >= 0 && indeks < liczbaObrazow) {
obroc90(&obrazy[indeks]);
}
break;
case 5:
printf("Podaj indeks obrazu: ");
scanf("%d", &indeks);
if (indeks >= 0 && indeks < liczbaObrazow) {
float poziom;
printf("Podaj poziom szumu (0-1): ");
scanf("%f", &poziom);
zaszumObraz(&obrazy[indeks], poziom);
}
break;
case 6:
printf("Podaj indeks obrazu: ");
scanf("%d", &indeks);
if (indeks >= 0 && indeks < liczbaObrazow) {
filtrMedianowy(&obrazy[indeks]);
}
break;
case 7:
printf("Podaj indeks obrazu: ");
scanf("%d", &indeks);
if (indeks >= 0 && indeks < liczbaObrazow) {
printf("Podaj nazwe pliku CSV: ");
scanf("%s", nazwaPliku);
histogramDoCSV(&obrazy[indeks], nazwaPliku);
}
break;
case 8:
wyswietlListeObrazow();
break;
case 9:
printf("Podaj indeks obrazu: ");
scanf("%d", &indeks);
if (indeks >= 0 && indeks < liczbaObrazow) {
usunObraz(indeks);
}
break;
default:
printf("Niepoprawna opcja.\n");
}
}
for (int i = 0; i < liczbaObrazow; i++) {
zwolnijTablice2D(obrazy[i].piksele, obrazy[i].wysokosc);
}
return 0;
}
DODATKOWA funkcja ktora ma generowac nowy obraz gradient pionowy od bialego do czarnego