#include #include #include #define EXIT_SUCCESS 0 #define EXIT_WRONGCOMMANDLINE 1 #define EXIT_MEMORY 2 #define EXIT_OPENFILE 3 #define EXIT_WRONGINPUTFORMAT 4 #define EXIT_INCONSISTENCY 5 #include "listanodi.h" #include "listaarchi.h" #define LUNGHEZZA 80 typedef char** immagine; typedef struct _grafo { int NumNodi; int NumArchi; listanodi *LN; } grafo; void LeggeIstruzioni (int argc, char *argv[], char *ImageFile); void CaricaImmagini (char *ImageFile, int *pw, int *ph, immagine *pI); void DistruggeImmagine (immagine *pI, int h); grafo *CreaGrafo (); void DistruggeGrafo (grafo *G); void StampaGrafo (grafo* G); void ins_nodo (nodo *N, grafo *G); void ins_arco (arco *A, grafo *G); void CostruisceGrafoDadi (int w, int h, immagine I, grafo *G); void CompConnesse (grafo *GD, int *pNumComp, int *CompD); void StampaComponenti (grafo *G, int NumComp, int *Comp); void CostruisceGrafoPallini (grafo *GD, int *Comp, int d, grafo *GP); int main(int argc, char *argv[]) { char ImageFile[LUNGHEZZA+1]; immagine I; int w, h; grafo *GD, *GP; int d, NumDadi; int *CompD, *CompP; int NumPallini; // 1) Interpretazione della linea di comando LeggeIstruzioni(argc,argv,ImageFile); // 2) Caricamento dell'immagine CaricaImmagini(ImageFile,&w,&h,&I); // 3a) Allocazione del grafo ausiliario dei pixel appartenenti ai dadi GD = CreaGrafo(); // 4a) Costruzione del grafo ausiliario dei pixed-dadi CostruisceGrafoDadi(w,h,I,GD); // 5a) Stampa del grafo dei pixed-dadi StampaGrafo(GD); // 3b) Allocazione del vettore delle componenti connesse per i dadi CompD = (int *) calloc(GD->NumNodi+1,sizeof(int)); if (CompD == NULL) { printf("Memoria insufficiente per allocare il vettore delle componenti del grafo dei pixel-dadi!\n"); exit(EXIT_MEMORY); } // 4b) Identificazione dei dadi CompConnesse(GD,&NumDadi,CompD); // 5b) Stampa dei pixel appartenenti a ciascun dado StampaComponenti(GD,NumDadi,CompD); for (d = 1; d <= NumDadi; d++) { // 3c) Allocazione del grafo ausiliario dei pixel appartenenti ai pallini GP = CreaGrafo(); // 4c) Conteggio del numero di pallini contenuti nel dado corrente CostruisceGrafoPallini(GD,CompD,d,GP); // 3c') Allocazione del vettore delle componenti per i pallini CompP = (int *) calloc(GP->NumNodi+1,sizeof(int)); if (CompP == NULL) { printf("Memoria insufficiente per allocare il vettore delle componenti del grafo dei pixel-dadi!\n"); exit(EXIT_MEMORY); } // 4c') Identificazione dei pallini CompConnesse(GP,&NumPallini,CompP); // 5c) Stampa dei pixel appartenenti ad ogni pallino StampaComponenti(GP,NumPallini,CompP); // 5c') Stampa del numero totale di pallini printf("%d ",NumPallini); // 6c e 6c') Deallocazione del grafo ausiliario dei pixel appartenenti ai pallini // e del vettore delle componenti per i pallini DistruggeGrafo(GP); free(CompP); } printf("\n"); // 6) Deallocazione delle strutture dati DistruggeGrafo(GD); DistruggeImmagine(&I,h); free(CompD); return EXIT_SUCCESS; } void LeggeIstruzioni (int argc, char *argv[], char *ImageFile) { if (argc != 2) { printf("Command line format wrong!\n"); exit(EXIT_WRONGCOMMANDLINE); } strcpy(ImageFile,argv[1]); } void CaricaImmagini (char *ImageFile, int *pw, int *ph, immagine *pI) { FILE *fImageFile; int i; fImageFile = fopen(ImageFile,"r"); if (fImageFile == NULL) { printf("File %s does not exist!\n",ImageFile); exit(EXIT_OPENFILE); } if (fscanf(fImageFile,"%d %d\n",pw,ph) != 2) { printf("Nella prima riga mancano le dimensioni dell'immagine!\n"); exit(EXIT_WRONGINPUTFORMAT); } *pI = (immagine) calloc(*ph,sizeof(char *)); if (*pI == NULL) { printf("Memoria insufficiente per allocare l'immagine!\n"); exit(EXIT_MEMORY); } for (i = 0; i < *ph; i++) { (*pI)[i] = (char *) calloc(*pw+2,sizeof(char)); if ((*pI)[i] == NULL) { printf("Memoria insufficiente per allocare la riga %d dell'immagine!\n",i+1); exit(EXIT_MEMORY); } fgets((*pI)[i],*pw+2,fImageFile); } fclose(fImageFile); } void DistruggeImmagine (immagine *pI, int h) { int i; for (i = 0; i < h; i++) free((*pI)[i]); free(*pI); *pI = NULL; } grafo *CreaGrafo () { grafo *G; G = (grafo *) malloc(sizeof(grafo)); if (G == NULL) { printf("Memoria insufficiente per allocare il grafo!\n"); exit(EXIT_MEMORY); } G->NumNodi = 0; G->NumArchi = 0; G->LN = crealistanodi(); return G; } void DistruggeGrafo (grafo *pG) { posnodo *pn; for (pn = primolistanodi(pG->LN); !finelistanodi(pn,pG->LN); pn = succlistanodi(pn)) distruggelistaarchi(&pn->LA); // Distrugge la lista degli archi (vuota) dell'elemento sentinella distruggelistaarchi(&pG->LN->LA); distruggelistanodi(&pG->LN); pG->NumArchi = 0; pG->NumNodi = 0; } void ins_nodo (nodo *N, grafo *G) { G->NumNodi++; N->indice = G->NumNodi; inslistanodi(N,primolistanodi(G->LN)); } void ins_arco (arco *A, grafo *G) { G->NumArchi++; A->indice = G->NumArchi; inslistaarchi(A,primolistaarchi(A->orig->LA)); } void StampaGrafo (grafo *G) { posnodo *pn; posarco *pa; for (pn = primolistanodi(G->LN); !finelistanodi(pn,G->LN); pn = succlistanodi(pn)) for (pa = primolistaarchi(pn->LA); !finelistaarchi(pa,pn->LA); pa = succlistaarchi(pa)) printf("(%d,%d,%c)-(%d,%d,%c)\n",pa->orig->i,pa->orig->j,pa->orig->Tipo, pa->dest->i,pa->dest->j,pa->dest->Tipo); } void CostruisceGrafoDadi (int w, int h, immagine I, grafo *G) { int i, j; nodo *N; arco *A; posnodo *pn1, *pn2; // Per ogni pixel appartenente a un dado o a un pallino, aggiunge un nodo for (i = 0; i < h; i++) for (j = 0; j < w; j++) if ( (I[i][j] == '*') || (I[i][j] == 'X') ) { N = creanodo(i,j,I[i][j]); ins_nodo(N,G); } // Per ogni coppia di nodi corrispondenti a pixel adiacenti, aggiunge un arco for (pn1 = primolistanodi(G->LN); !finelistanodi(pn1,G->LN); pn1 = succlistanodi(pn1)) for (pn2 = succlistanodi(pn1); !finelistanodi(pn2,G->LN); pn2 = succlistanodi(pn2)) if ( abs(pn1->i-pn2->i) + abs(pn1->j-pn2->j) == 1 ) { A = creaarco(pn1,pn2); ins_arco(A,G); A = creaarco(pn2,pn1); ins_arco(A,G); } } void CostruisceGrafoPallini (grafo *GD, int *Comp, int d, grafo *GP) { } void CompConnesse (grafo *G, int *pNumComp, int *Comp) { *pNumComp = 0; } void StampaComponenti (grafo *G, int NumComp, int *Comp) { }