/************************************************************** #Programa#: #lab02.c# #Autor#: #Alexandre Falcão# #Data#: #27/07/2001# #Descrição#: #Laboratório de matrizes (implementação linear).# #Uso#: #lab02 < arq.tes > arq.res# #Parâmetros#: #entrada#: #arq.tes#: #Arquivo de teste.# #saída#: #arq.res#: #Arquivo com os resultados do teste.# #Modificação#: #data#: #99/99/9999# #autor#: #Alexandre Falcão# #descrição#: #inexistente# **************************************************************/ #include "lab02.h" /* Funções que não estão na libdados */ /* Ler Matriz */ MatrizL *LerMatriz() { int l,c,nl,nc; MatrizL *m; fscanf(stdin,"%d %d",&nl,&nc); m = matlCria(nl,nc); for (l=0; l < m->nl; l++) for (c=0; c < m->nc; c++) fscanf(stdin,"%d",&m->info[matlInd(m,l,c)]); return(m); } /* Grava Matriz */ void GravaMatriz(MatrizL *m) { int l,c; fprintf(stdout,"matriz %dl x %dc:\n", m->nl, m->nc); for (l=0; l < m->nl; l++) { for (c=0; c < m->nc; c++) fprintf(stdout,"%4d ", m->info[matlInd(m,l,c)]); fprintf(stdout,"\n"); } } /* Ler Imagem */ MatrizL *LerImagem(char *arqimg) { int l,c,nl,nc,max; char type[10]; unsigned char *img; MatrizL *m; FILE *ent; /* ler imagem tipo P5 (PGM BINÁRIA) */ ent = fopen(arqimg,"rb"); fscanf(ent,"%s",type); fscanf(ent,"%d %d",&nc,&nl); fscanf(ent,"%d",&max); img = (unsigned char *) calloc(nl*nc,sizeof(unsigned char)); fread(img,nl*nc,sizeof(unsigned char),ent); fclose(ent); /* copia para matriz */ m = matlCria(nl,nc); for (l=0; l < m->nl; l++) for (c=0; c < m->nc; c++) m->info[matlInd(m,l,c)] = (int)img[matlInd(m,l,c)]; free(img); return(m); } /* Grava Imagem */ void GravaImagem(char *arqimg, MatrizL *m) { int l,c,nl,nc,max,min,inf; char type[10]; unsigned char *img; FILE *sai; /* grava imagem tipo P5 (PGM BINÁRIA) */ if (m == NULL) { comAviso(AVS1, "GravaImagem"); exit; } sai = fopen(arqimg,"w"); if (sai == NULL) { printf("\nErro ao abrir o arquivo '%s'.", arqimg); exit(-1); } nl = m->nl; nc = m->nc; img = (unsigned char *) calloc(nl*nc,sizeof(unsigned char)); /* calcula valor max,min para a matriz */ min = max = m->info[0]; for (l=0; l < m->nl; l++) for (c=0; c < m->nc; c++) { inf = m->info[matlInd(m,l,c)]; if (max < inf) max = inf; else if (min > inf) min = inf; } /* copia da matriz (normalizado entre 0 e 255) */ for (l=0; l < m->nl; l++) for (c=0; c < m->nc; c++) { inf = m->info[matlInd(m,l,c)]; img[matlInd(m,l,c)] = (unsigned char) (255 * (inf-min) / (max-min)); } /* Grava o cabecalho do arquivo de imagem PGM */ max = 255; sprintf(type, "P5\n"); fprintf(sai, "%s", type); fprintf(sai, "%d %d\n", nc, nl); fprintf(sai, "%d\n", max); /* Grava a imagem */ if ( fwrite(img, sizeof(unsigned char), nl*nc, sai) != (size_t) nl*nc) { printf("\nErro na gravacao da imagem.\n"); fclose(sai); exit(-1); } fprintf(sai, "%c", EOF); free(img); /* Fecha arquivo de imagem PGM */ fclose(sai); } MatrizL *matlInverte(MatrizL *m) { MatrizL *mi = NULL; int i,n; if (m == NULL) comAviso(AVS1,"matlInverte"); else { mi = matlCria(m->nl, m->nc); n = m->nc * m->nl; for (i=0; i < n; i++) mi->info[n-1-i] = m->info[i]; } return mi; } MatrizL *Convolucao(MatrizL *imagem, MatrizL *kernel){ MatrizL *m = NULL; MatrizL *ikernel = NULL; int i,j,x1, x2, y1, y2, c, cx, cy; cx = (kernel->nc - 1) /2; cy = (kernel->nl - 1) /2; if ((imagem == NULL) || (kernel == NULL)) comAviso(AVS1,"Convolucao"); else { m = matlCria(imagem->nl, imagem->nc); ikernel = matlInverte(kernel); for (y1=0; y1 < imagem->nl; y1++) for (x1=0; x1 < imagem->nc; x1++) { c=0; for (x2=x1-cx, j=0; x2nc-cx); x2++, j++) for (y2=y1-cy, i=0; y2nl-cy); y2++, i++) if ((y2 >=0) && (y2nl) && (x2 >=0) && (x2 nc)) c += imagem->info[matlInd(imagem,y2,x2)] * ikernel->info[matlInd(ikernel,i,j)]; m->info[matlInd(m,y1,x1)] = c; } matlDestroi(ikernel); } return m; } int main(int argc, char **argv) { MatrizL *aux,*m[5]={NULL,NULL,NULL,NULL,NULL}; /* Cinco vetores a serem manipulados */ char acao[10]; /* Acao a ser tomada conforme indicado na entrada */ int i,j,k; /* variáveis auxiliar */ char s[255] = "\0"; /* ------------------------------------------------------------ VÁLIDO APENAS PARA LINUX Declarações para verificação do uso da memória dinâmica. A variável 'lixo' está sendo usada apenas para contornar um problema do funcionamento das funções da biblioteca 'malloc': a memória por ela apontada é desalocada logo a seguir! ------------------------------------------------------------ */ void *lixo = malloc(1); /* truque: variável auxiliar */ struct mallinfo info; int MemDinInicial, MemDinFinal; free(lixo); /* truque */ info = mallinfo(); MemDinInicial = info.uordblks; /* ------------------------------------------------------- */ /* Executa o teste */ fscanf(stdin,"%s",acao); while(strcmp(acao,"t")!=0) { switch(*acao) { case 'l': /* Ler matriz */ fscanf(stdin,"%d",&i); if (m[i] != NULL) matlDestroi(m[i]); m[i] = LerMatriz(); break; case 'g': /* Grava matriz */ fscanf(stdin,"%d",&i); GravaMatriz(m[i]); break; case 'L': /* Le imagem do arquivo para matriz */ fscanf(stdin,"%s %d",s, &i); if (m[i] != NULL) matlDestroi(m[i]); m[i] = LerImagem(s); break; case 'G': /* Grava martiz para um arquivo de imagem */ fscanf(stdin,"%d %s",&i, s); GravaImagem(s, m[i]); break; case 's': /* Soma de duas matrizes */ fscanf(stdin,"%d %d %d", &i,&j,&k); if (m[k] != NULL) matlDestroi(m[k]); m[k] = matlSoma(m[i], m[j]); break; case 'm': /* Multiplica duas matrizes */ fscanf(stdin,"%d %d %d", &i,&j,&k); if (m[k] != NULL) matlDestroi(m[k]); m[k] = matlMultiplica(m[i], m[j]); break; case 'e': /* Escala matriz */ fscanf(stdin,"%d %d %d", &i,&j,&k); if (m[k] != NULL) matlDestroi(m[k]); m[k] = matlEscala(m[i], j); break; case 'r': /* Calcula matriz transposta */ fscanf(stdin,"%d",&i); aux = matlTransposta(m[i]); GravaMatriz(aux); matlDestroi(aux); break; case 'c': /* Convolve duas matrizes */ fscanf(stdin,"%d %d %d", &i,&j,&k); if (m[k] != NULL) matlDestroi(m[k]); m[k] = Convolucao(m[i], m[j]); break; default: fprintf(stderr,"Ação %s inválida\n",acao); exit(-1); } fscanf(stdin,"%s",acao); } for (i=UM; i <= CINCO; i++) if (m[i]!=NULL) matlDestroi(m[i]); /* ------------------------------------------------------------ Verificação do uso da memória dinâmica. ------------------------------------------------------------ */ info = mallinfo(); MemDinFinal = info.uordblks; if (MemDinInicial!=MemDinFinal) printf("\n\nMemória dinâmica não foi totalmente liberada (%d,%d)\n", MemDinInicial,MemDinFinal); /* ------------------------------------------------------------ */ printf("\n\nFim da execução.\n\n"); return 0; } /* lab02 */ /* author: Gustavo Sverzut Barbieri (http://www.gustavobarbieri.com.br) */