#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
extern void escalaDeGrises(char* datos, unsigned filas, unsigned columnas);
extern void escalaDeGrises2(char* datos, unsigned filas, unsigned columnas);
extern void prewitt_asm(char* datos, char* copia, unsigned filas, unsigned columnas);
extern void sobel_asm(char* datos, char* copia, unsigned filas, unsigned columnas);
extern void roberts_asm(char* datos, char* copia, unsigned filas, unsigned columnas);
extern void umbralizar_asm(char* datos, unsigned filas, unsigned columnas, unsigned th, unsigned tl);
/* r1 = realzar bordes con el operador de Roberts.
r2 = realzar bordes con el operador de Prewitt.
r3 = realzar bordes con el operador de Sobel.
m1 = monocromatizar con = 1.
=∞
m2 = monocromatizar con
u = umbralizar (en este caso tambien toma dos enteros para los umbrales maximo y
minimo)
i = input (nombre del archivo)
*/
// TODO: completar este help y hacer que se imprima cuando hay un error.
void help(){
printf("Parametros:\n");
printf("--help (-h) Muestra esta ayuda\n");
printf("--m1 (-m) Convierte a escala de grises con");
printf("promedios\n");
printf("--m2 (-g) Convierte a escala de grises con maximo\n");
printf("--input (-i) Nombre de archivo de entrada");
printf(" (obligatorio)\n");
printf("--output (-o) Nombre de archivo de salida");
printf(" (obligatorio)\n");
printf("--r1 (-r) Deteccion de bordes con el operador de");
printf("Roberts\n");
printf("--r2 (-p) Deteccion de bordes con el operador de");
printf("Prewitt\n");
printf("--r3 (-s) Deteccion de bordes con el operador de");
printf("Sobel\n");
printf("--umbralizar (-u) Aplicar umbralizacion por histeresis. ");
printf("Obligatorio: limite\n");
printf(" inferior y superior\n");
printf("Para umbralizar es necesario seleccionar un filtro\n");
printf("Por defecto se monocromatiza con promedios\n");
}
int main(int argc, char **argv){
const char* const op_cortas = "hmgrpsi:o:u:" ; // posibles parametros, van
//con -
int siguiente_opcion;
// forma larga para las opciones. En consola van con --
const struct option op_largas[] = {
{ "m1", 0, NULL, 'm'},
{ "m2", 0, NULL, 'g'},
{ "input", 1, NULL, 'i'},
{ "output", 1, NULL, 'm'},
{"r1", 0, NULL, 'r'},
{"r2", 0, NULL, 'p'},
{"r3", 0, NULL, 's'},
{"umbralizar", 1, NULL, 'u'},
{"help", 0, NULL, 'h'},
{ NULL, 0, NULL, 0 }
};
// si no puso parametros, le decimos que necesitamos el archivo
if (argc == 1) {
printf("No se especifico una imagen!\n");
help();
}
// declaracion de variables
char * ficheroEntrada; // nombre del archivo
char * ficheroSalida = NULL;
char metodo='m'; // metodo de monocromatizacion
char metodoBordes = 'f'; // metodo de deteccion de bordes
unsigned min, max; // parametros para umbralizar
int umbralizo = 0; // flag de umbralizar
while (1) {
// llamamos a la función getopt
siguiente_opcion = getopt_long (argc, argv, op_cortas, op_largas, NULL);
if (siguiente_opcion == -1) // no hay mas opciones
break;
// para cada parametro, seteamos el flag correspondiente
switch (siguiente_opcion) {
case 'm' : /* -m o --m1 */
metodo = 'm' ;
break;
case 'g' : /* -g o --m2 */
metodo = 'g' ;
break;
case 'r' : /* -r o --r1 */
metodoBordes = 'r' ;
break;
case 's' : /* -s o --r2 */
metodoBordes = 's' ;
break;
case 'p' : /* -p o --r3 */
metodoBordes = 'p' ;
break;
case 'u' : /* -u ó --umbralizar */
umbralizo = 1;
sscanf(optarg,"%d",&min);
break;
case 'i' : /* -i ó --input */
ficheroEntrada = optarg; /* optarg contiene el argumento de -o */
break;
case 'o' : /* -o ó --output */
ficheroSalida = optarg; /* optarg contiene el argumento de -o*/
break;
case 'h' : /* -h ó --help */
help();
return 0;
case -1 : /* No hay más opciones */
break;
default : /* Algo más? No esperado. Abortamos */
printf("Formato de opciones invalido!\n");
help();
return 1;
}
}
// Para umbralizar se necesitan 2 parametros. Como getOpt solo toma uno, el otro lo coloca en
// los no identificados. Para evitar que se pongan mas de uno, pedimos que solo halla un parametro no
// identificado.
if(umbralizo && optind == argc -1)
sscanf(argv[optind],"%d",&max);
// si hay parametros de mas paramos
if((!umbralizo && optind < argc) || (umbralizo && optind != argc -1) ) {
printf("Formato de opciones invalido!\n");
help();
return 1;
}
// abrimos el archivo
FILE* fichero;
FILE* salida;
int ancho, alto, offset;
char marca1, marca2;
if (ficheroSalida == NULL) {
puts("No se pudo crear archivo de salida\n");
return 1;
}
fichero = fopen(ficheroEntrada, "rbw+");
salida = fopen(ficheroSalida, "wb");
if (fichero == NULL) {
puts("Archivo no encontrado! Ingreso el nombre correcto?\n");
help();
return 1;
}
if (salida == NULL) {
puts("No se pudo crear archivo de salida\n");
return 1;
}
else {
marca1 = fgetc(fichero); // leemos los dos primeros bytes
marca2 = fgetc(fichero);
if (marca1 =='B' && marca2 =='M') { // si son BM, sino paramos
fseek(fichero, 18, SEEK_SET); // posicion 18: ancho
fread(&ancho, 1, 4, fichero);
fread(&alto, 1, 4, fichero); // siguiente dato: alto
fseek(fichero, 10, SEEK_SET); // tomamos el offset hasta los pixeles
fread(&offset,1,4,fichero);
short int sumandoextra = (4 - (ancho*3 % 4)) % 4;
unsigned int dimension = (ancho * 3 + sumandoextra) * alto; // cada pixel son 24 bits, o sea 3 bytes
char * matriz = (char*) malloc(dimension); // memoria para levantar el archivo
char * matriz2 = (char*) malloc(dimension); // memoria para guardar los bordes detectados
if(matriz != 0) {
fseek(fichero, offset, SEEK_SET);
fread(matriz, dimension, 1, fichero);
// operamos segun los parametros recibidos
if(metodo == 'm'){
printf("Monocromatizando...\n");
escalaDeGrises(matriz, alto, 3*ancho);
}
else if(metodo == 'g'){
printf("Monocromatizando...\n");
escalaDeGrises2(matriz, alto, 3*ancho);
}
if(metodoBordes == 's') {
printf("Aplicando Sobel...\n");
sobel_asm(matriz, matriz2, alto, ancho);
}
else if (metodoBordes == 'r') {
printf("Aplicando Roberts...\n");
roberts_asm(matriz, matriz2, alto, ancho);
}
else if (metodoBordes == 'p'){
printf("Aplicando Prewitt...\n");
prewitt_asm(matriz, matriz2, alto, ancho);
}
if(umbralizo && metodoBordes == 'f'){
printf("Para umbralizar se debe aplicar un filtro primero");
printf("\nSeleccione un filtro para poder umbralizar\n");
help();
umbralizo = 0;
}
if(umbralizo) { // llamada a umbralizar
if(min > 255){
printf("Adevertencia: los valores mayores a 255, seran interpretados como 255.\n");
min = 255;
}
if(max > 255){
printf("Adevertencia: los valores mayores a 255, seran interpretados como 255.\n");
max = 255;
}
printf("Umbralizando con umbral superior %u y umbral inferior %u ...\n", max, min);
umbralizar_asm(matriz2,alto, ancho, max, min);
}
char * info = (char*) malloc(offset);
fseek(fichero, 0, SEEK_SET);
fread(info,offset,1,fichero);
fwrite(info, offset, 1, salida);
fseek(fichero, offset, SEEK_SET);
if(metodoBordes != 'f'){
fwrite(matriz2, dimension, 1, salida);
}
else{
fwrite(matriz, dimension, 1, salida);
}
fclose(fichero);
fclose(salida);
free(matriz);
free(matriz2);
free(info);
}
}
return 0;
}
}