/* Veja {exemplo.h}. */ /* Last edited on 2009-03-06 00:05:23 by stolfi */ #include /* PROTÓTIPOS ADICIONAIS: */ void ex_process_images(operation_t op, flt_image_t *A, flt_image_t *B, flt_image_t *R); /* Aplica a operação {op} nas imagens {A} e {B}, colocando o resultado em {R}. */ /* PROGRAMA PRINCIPAL: */ int main(int argc, char** argv) { /* Pega os parâmetros da linha de comando: */ options_t *o = ex_parse_options(argc, argv); /* Lê as duas imagens de entrada {A,B}: */ flt_image_t *A = ex_read_image(NULL, o->img_name[0]); flt_image_t *B = ex_read_image(NULL, o->img_name[1]); /* Define o tamanho {R_sz[i]} da imagem-resultado em cada eixo {i}: */ ix_size_t R_sz[NDIM]; ix_size_fill(NDIM, R_sz, MAXSIZE); /* Inicializa com tamanho máximo. */ ix_size_min(NDIM, R_sz, A->ix.sz); /* Não exceder o tamanho de {A}. */ ix_size_min(NDIM, R_sz, B->ix.sz); /* Não exceder o tamanho de {B}. */ /* Cria a imagem-resultado {R} na memória: */ flt_image_t *R = flt_image_alloc(R_sz); /* Calcula a imagem-resultado: */ ex_process_images(o->op, A, B, R); /* Escreve a imagem-resultado na saída padrão: */ ex_write_image(stdout, NULL, R) return 0; } /* PROCESSAMENTO DAS IMAGENS: */ void ex_process_images(operation_t op, flt_image_t *A, flt_image_t *B, flt_image_t *R) { /* Vetor de tamanho das imagens: */ ix_size_t sz[NIX]; /* {sz[i]} é o tamanho da imagem na direção do eixo {i}. */ flt_image_get_size(R, sz); /* Pega as dimensões {sz[0..NIX-1]} da imagem {R}. */ flt_image_check_size(A, sz, TRUE); /* Exige que a imagem {A} tenha o mesmo tamanho. */ flt_image_check_size(B, sz, TRUE); /* Exige que a imagem {B} tenha o mesmo tamanho. */ /* Vetor de índices de amostra: */ ix_index_t ix[NIX]; /* {ix[i]} é o índice na direção do eixo {i}. */ bool_t done = ix_assign_min(NIX, ix, sz, NULL, NULL); /* Inicializa todos os índices com 0. */ while (! done) { float *pA = flt_image_get_sample_address(A, ix); /* Endereço da amostra de {A}. */ float *pB = flt_image_get_sample_address(B, ix); /* Endereço da amostra de {B}. */ float *pC = flt_image_get_sample_address(C, ix); /* Endereço da amostra de {C}. */ switch (op) { case op_ADD: (*pR) = (*pA) + (*pB); break; case op_MUL: (*pR) = (*pA) * (*pB); break; default: demand(FALSE, "operação inválida"); } done = ix_next_C(NIX, ix, sz, NULL, NULL); /* Pega índices da próxima amostra. */ } } /* ANÁLISE DA LINHA DE COMANDO: */ options_t *parse_options(int argc, char **argv) { /* INICIALIZA A ANÁLISE: */ /* Cria e incializa o analisador de linha de comando {pp}: */ argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); /* Processa as opções "-help" e "-info": */ argparser_process_help_info_options(pp); /* Aloca o registro {o} onde os parâmetros serão guardados: */ options_t *o = (options_t *)malloc(sizeof(options_t)); /* PEGA PARÂMETROS COM PALAVRA-CHAVE: */ /* Analiza a opção "-op {OP}": */ argparser_get_keyword(pp, "-op"); { char *op_name = argparser_get_next(pp); if (strcmp(op_name, "add") == 0) { o->op = op_ADD; } else if (strcmp(op_name, "mul") == 0) { o->op = op_MUL; } else { argparser_error(pp, "operação inválida"); } } /* PEGA PARÂMETROS POSICIONAIS: */ /* Pule para o primeiro parâmetro posicional: */ argparser_skip_parsed(pp); /* Pega o nome da imagem {A}: */ if (argparser_next(pp) != NULL) { o->A_name = argparser_get_next(pp); } else { o->A_name = "-"; } /* pega o nome da imagem {B}: */ if (argparser_next(pp) != NULL) { o->B_name = argparser_get_next(pp); } else { o->B_name = "-"; } /* FINALIZA A ANÁLISE: */ /* Verifica se há argumentos sobrando: */ argparser_finish(pp); return o; }