//estos ficheros de cabecera deben estar en el mismo directorio que los de codigo (o si no, indicarle al compilador donde buscar los include) #include "FicherosBMP_ansi.h" #include "Contadorciclos_ansi.h" #include #include #include #include struct t_imgrgb { // el orden RGB es el contrario porque los píxeles se almacenan al reves: // desde el final del fichero hasta el ppio unsigned char B; unsigned char G; unsigned char R; unsigned char ALFA; }; /////////////////////////////////////////////////////////////////////////////// struct t_imgrgb *buf_imgrgb ; FILE * pf; /////////////////////////////////////////////////////////////////////////////// //funcion para terminar el programa, cerrando ficheros, liberando memoria, etc void fin_prog (int); /////////////////////////////////////////////////////////////////////////////// int main(void) { unsigned int i, ind_max, ind_permutado ; unsigned char kk[54], colores[4], color_max ; long int tamaño ; _Win4xBitmapHeader header; short int bytes_por_pixel ; char nomfh[256]; unsigned char alfaVal; printf ("- Dame fichero entrada (con extension): "); gets (nomfh); if ( (pf=fopen(nomfh, "rb")) == NULL) fin_prog (-1); //fseek (pf, 14, SEEK_CUR ); fread (kk, 1, 14, pf) ; //leo los 14 bytes de la primera cabecera, solo para copiarlos en fichero de salida fread (&header.Size, 1, sizeof(header.Size), pf) ;//leo el primer campo //que contiene el tamaño de la segunda cabecera (es la importante) fread (&header.Size + 1, 1, (header.Size)-sizeof(header.Size), pf) ;//leo el resto de campos //de la segunda cabecera printf ("- Caraceristicas fichero original:\n"); printf (" - Header Size=%ld, Width=%ld, Height =%ld\n", header.Size ,header.Width, header.Height); printf (" - BitsPerPixel=%d, SizeOfBitmap=%ld\n", header.BitsPerPixel, header.SizeOfBitmap); if ( header.BitsPerPixel != 32) fin_prog (-2);//tamaño de imagen en pixeles bytes_por_pixel = (header.BitsPerPixel / 8) ; //debe ser 3 evidentemente !!!!!!!! (4) tamaño = header.Width * header.Height; //en pixeles printf ("- Numero de bytes reales Width * Height * BitsPerPixel / 8 =%ld\n", tamaño * bytes_por_pixel ); if ( header.SizeOfBitmap != tamaño * bytes_por_pixel ) { printf (" *** La cabecera del bmp original no es estandar; \n"); } buf_imgrgb = (t_imgrgb *) calloc (header.SizeOfBitmap, 1); i = fread (buf_imgrgb , 1, (header.SizeOfBitmap), pf) ; if ( header.SizeOfBitmap != i ) fin_prog (-3); printf ("\n\n"); srand( (unsigned)time( NULL ) ); for(int z =0;z<5;z++) { //////////////////////////////////////////// //////////////////////////////////// //////////////////////////////////// //////////////////////////////////// unsigned int toverhead_alto, toverhead_bajo; unsigned int toverhead_alto_prov, toverhead_bajo_prov; unsigned int t1_alto, t1_bajo; unsigned int t0_alto, t0_bajo; unsigned int j; double nanoseg ; LeerCiclosAnsi (&t0_alto,&t0_bajo); LeerCiclosAnsi (&t1_alto,&t1_bajo); RestarCiclosAnsi (&toverhead_alto, &toverhead_bajo, &t1_alto,&t1_bajo,&t0_alto,&t0_bajo); //repito 5 veces para hallar overhead mas bajo: for(j=0;j<5;j++) { LeerCiclosAnsi (&t0_alto,&t0_bajo); LeerCiclosAnsi (&t1_alto,&t1_bajo); RestarCiclosAnsi (&toverhead_alto_prov, &toverhead_bajo_prov, &t1_alto,&t1_bajo,&t0_alto,&t0_bajo); if(toverhead_bajo_prov < toverhead_bajo)//se supone que toverhead_alto siempre será cero toverhead_bajo = toverhead_bajo_prov ; } ImprimirCiclosAnsi (" Ciclos de overhead (minimo) = ", &toverhead_alto, &toverhead_bajo); LeerCiclosAnsi (&t0_alto,&t0_bajo); //////////////////////////////////// //////////////////////////////////// //////////////////////////////////// //////////////////////////////////////////// for (alfaVal=255 ; alfaVal>0 ; alfaVal--) { unsigned int cond_fin = (int)(buf_imgrgb+header.SizeOfBitmap); __asm { lea eax,buf_imgrgb // r1 = &buf_imgrgb bucle: ldps XMM0, [eax] // carga un pixel con su B G R ALPHA ldss XMM1, alfaVal // cargamos alfaVal en la parte baja de MM1 shufps XMM1,XMM1,0 // replicamos alfaVal cmpgtps XMM2,XMM0,XMM1 // creamos la máscara del condicional cierta cmpleps XMM3,XMM0,XMM1 // creamos la máscara del condicional falsa andps XMM2,XMM2,XMM1 // res con cond cierta andps XMM3,XMM3,XMM0 // res con cond falsa orps XMM2,XMM2,XMM3 // resultado stps [eax], XMM2 // lo almacenamos addi eax,eax,16 slti ebx,eax,cond_fin bnez ebx,bucle } // for (i=0;i <(header.SizeOfBitmap)/4 ; i++) // /* le sumo 2 y redondeo a multiplo de 3 // porque no estan bien hechas las cuentas en algunos bmp. NO coincide // header.Width * header.Height con el numero de pixeles reales // */ // { // colores[0] = (buf_imgrgb + i)->B; // colores[1] = (buf_imgrgb + i)->G; // colores[2] = (buf_imgrgb + i)->R; // colores[3] = (buf_imgrgb + i)->ALFA; // // if (colores[3] > alfaVal) colores[3] = alfaVal; // if (colores[2] > alfaVal) colores[2] = alfaVal; // if (colores[1] > alfaVal) colores[1] = alfaVal; // if (colores[0] > alfaVal) colores[0] = alfaVal; // // (buf_imgrgb + i)->B = colores[0]; // (buf_imgrgb + i)->G = colores[1]; // (buf_imgrgb + i)->R = colores[2]; // (buf_imgrgb + i)->ALFA = colores[3]; // } } //////////////////////////////////// //////////////////////////////////// //////////////////////////////////// //////////////////////////////////// LeerCiclosAnsi (&t1_alto,&t1_bajo); RestarCiclosAnsi (&t1_alto,&t1_bajo, &t1_alto,&t1_bajo,&t0_alto,&t0_bajo); //finalmente, resto el overhead: RestarCiclosAnsi (&t1_alto,&t1_bajo, &t1_alto,&t1_bajo,&toverhead_alto, &toverhead_bajo); ImprimirCiclosAnsi (" - Duracion total en Ciclos = ", &t1_alto,&t1_bajo); printf (" - Duracion total en seg = %le \n", ConvertirATiempoAnsi(&t1_alto,&t1_bajo) ); nanoseg = ConvertirATiempoAnsi(&t1_alto,&t1_bajo)*1.0e9; printf( " - Duracion por pixel: %.2lf ciclos; %.2lf ns ; \n", ConvertirACiclosAnsi(&t1_alto,&t1_bajo) /(double)tamaño , nanoseg /(double)tamaño ); //////////////////////////////////// //////////////////////////////////// //////////////////////////////////// //////////////////////////////////// } fin_prog (0); return 0; } //*********************************************************************** // FUNCIONES //*********************************************************************** ////////////////////////////////////////////////////////////////////// //Funcion para imprimir mensajes tras finalizar el programa void fin_prog (int codigo_salida) { free(buf_imgrgb); fclose (pf); if (codigo_salida == 0) printf("\n- Programa termino bien\n"); else printf("\n- Error %d. La imagen no es ARGB\n", codigo_salida); //Dejar siempre lo siguiente para que no se cierre la ventana. printf( "\n- Pulse Intro para cerrar ventana \n"); fflush(stdin); getchar(); exit (codigo_salida); } //////////////////////////////////////////////////////////////////////