// // Programa simples, pouco eficiente e pouco robusto; tem como objectivo: // - ler uma imagem PPM de um ficheiro (apenas P6 sem comentarios, mas sem testar); // - aplicar uma funcao sobre a imagem (rodar 90 graus para a direita); // - guardar a nova imagem num outro ficheiro (PPM, tipo P6); // - medir o tempo total de execucao usando a func gettimeofday; // - medir o tempo medio de rodar um pixel, em ciclos de clock (CPE) // #include #include #include #include #define MAXSTR 100 // // Define estrutura de uma image PPM-P6 // typedef struct p6image P6image; typedef int Pixel[3]; struct p6image { int cols; int lines; int max; Pixel *pixels; }; /* $begin tod (from CS:APP) */ #include #include static struct timeval tstart; /* Record current time */ void start_timer() { gettimeofday(&tstart, NULL); } /* Get number of seconds since last call to start_timer */ double get_timer() { struct timeval tfinish; long sec, usec; gettimeofday(&tfinish, NULL); sec = tfinish.tv_sec - tstart.tv_sec; usec = tfinish.tv_usec - tstart.tv_usec; return sec + 1e-6*usec; } /* $end tod */ // // Ler um ficheiro com uma imagem P6 para uma estrutura com a imagem // void readp6(char *filename, P6image *img) { FILE *infp; char byte, str[MAXSTR]; int i, j, k; infp = fopen(filename, "rb"); fscanf(infp, "%s", str); fscanf(infp, "%d", &img->cols); fscanf(infp, "%d", &img->lines); fscanf(infp, "%d", &img->max); img->pixels = (Pixel*) malloc (img->cols*img->lines*sizeof(Pixel)); byte = fgetc(infp); /* ler char \n antes do inicio da imagem */ for(i=0; i < img->lines; i++) for(j=0; j < img->cols; j++){ for(k=0; k < 3; k++) img->pixels[i*img->cols+j][k] = fgetc(infp); } fclose(infp); } // // Gravar um ficheiro com uma imagem P6, de uma estrutura com uma imagem // void writep6(char* filename, P6image* img) { FILE *outfp; int i, j, k; outfp = fopen(filename, "w"); fprintf(outfp, "P6 %d %d %d ", img->cols, img->lines, img->max); fclose(outfp); outfp = fopen(filename, "ab"); for(i=0; i < img->lines; i++) for(j=0; j < img->cols; j++){ for(k=0; k < 3; k++) fputc(img->pixels[i*(img->cols)+j][k], outfp); } fclose(outfp); } // // Rodar a imagem P6 de 90 graus para a direita // void roda(P6image* img,P6image *newimg) { int i,j,k; newimg->cols=img->lines; newimg->lines=img->cols; newimg->max=img->max; newimg->pixels=(Pixel*) malloc (img->lines*img->cols*sizeof(Pixel)); for(k=0; k < 3; k++) for(i=0; i < img->lines; i++) for(j=0; j < img->cols; j++){ (newimg->pixels)[j*newimg->cols+newimg->cols-i][k]=(img->pixels)[i*img->cols+j][k]; } } /* * Routines for using the cycle counter */ static unsigned cyc_hi = 0; static unsigned cyc_lo = 0; void access_counter(unsigned *hi, unsigned *lo) { asm("rdtsc; movl %%edx,%0; movl %%eax,%1" /* Read cycle counter */ : "=r" (*hi), "=r" (*lo) /* and move results to */ : /* No input */ /* the two outputs */ : "%edx", "%eax"); } /* Record the current value of the cycle counter. */ void start_counter() { access_counter(&cyc_hi, &cyc_lo); } /* Return the number of cycles since the last call to start_counter. */ double get_counter() { unsigned ncyc_hi, ncyc_lo; unsigned hi, lo, borrow; double result; /* Get cycle counter */ access_counter(&ncyc_hi, &ncyc_lo); /* Do double precision subtraction */ lo = ncyc_lo - cyc_lo; borrow = lo > ncyc_lo; hi = ncyc_hi - cyc_hi - borrow; result = (double) hi * (1 << 30) * 4 + lo; if (result < 0) { fprintf(stderr, "Error: counter returns neg value: %.0f\n", result); } return result; } // // Programa principal // int main() { P6image img; P6image newimg; double t1,cpe; char nome[40]; printf("Nome do ficheiro PPM (P6) a rodar:"); scanf("%s",nome); start_timer(); /*Ler o ficheiro*/ readp6(nome, &img); /*Aquecer a cache*/ roda(&img,&newimg); /*Rodar a imagem 90graus direita*/ start_counter(); roda(&img,&newimg); cpe=get_counter(); cpe=cpe/(img.lines*img.cols); printf("CPE a quente (Rodar 90graus, P6, %dx%d pixeis): %.2f\n",newimg.lines,newimg.cols,cpe); /*Gravar o ficheiro*/ writep6("out2.ppm", &newimg); t1 = get_timer(); printf("%f segundos para ler a imagem da file, rodar e gravar de novo\n", t1); free(img.pixels); free(newimg.pixels); return 0; }