/*============================================================================ * Preparacao para 1o trabalho - TAD: Imagem * * Curso de Fundamentos da Computacao Grafica 2004.1, prof. Marcelo Gattass * *===========================================================================*/ #include #include #include #include //#include #include "glut.h" #include "Image.h" #include "math.h" #include "im.h" /*- implementação dos tipos: --------------------------------*/ struct image_imp { unsigned short width; /* largura (width) em pixels */ unsigned short height; /* altura (height) em pixels */ unsigned char *buf; /* buffer BGR */ }; struct img_statistics_imp { unsigned short width; /* largura (width) em pixels */ unsigned short height; /* altura (height) em pixels */ double *buf; /* buffer */ }; struct sequence_imp { unsigned short nframes; /* number of frames */ unsigned short width; /* largura (width) em pixels */ unsigned short height; /* altura (height) em pixels */ unsigned char *buf; /* buffer nframes*BGR */ }; struct map_imp { unsigned short width; /* largura (width) em pixels */ unsigned short height; /* altura (height) em pixels */ float *buf; /* buffer of float values */ }; /*-----------------------------------------------------------------*/ /* getuint e putuint: * Funções auxiliares para ler e escrever inteiros na ordem (lo-hi) * Note que no Windows as variaveis tipo "unsigned short int" sao armazenadas * no disco em dois bytes na ordem inversa. Ou seja, o numero 400, * por exemplo, que pode ser escrito como 0x190, fica armazenado em * dois bytes consecutivos 0x90 e 0x01. Nos sistemas UNIX e Mac * este mesmo inteiro seria armazenado na ordem 0x01 e 0x90. * O armazenamento do Windows e' chamado de "little endian" * (i.e., lowest-order byte stored first), e no sitemas Unix sao * "big-endian" (i.e., highest-order byte stored first). */ static int getuint(unsigned short *uint, FILE *input) { int got; unsigned char temp[2]; unsigned short tempuint; got = (int) fread(&temp, 1, 2, input); if (got != 2) return 0; tempuint = ((unsigned short)(temp[1])<<8) | ((unsigned short)(temp[0])); *uint = tempuint; return 1; } static int putuint(unsigned short uint, FILE *output) { int put; unsigned char temp[2]; temp[0] = uint & 0xff; temp[1] = (uint >> 8) & 0xff; put = (int) fwrite(&temp, 1, 2, output); if (put != 2) return 0; return 1; } /* * Implementação das operacoes do tipo imagem */ Image imgCreate (int w, int h) { Image img; img = (Image) malloc (sizeof(struct image_imp)); assert(img); img->width =(unsigned int) w; img->height =(unsigned int) h; img->buf = (unsigned char *) malloc (w * h * 3); assert(img->buf); return img; } void imgDestroy (Image img) { if (img) { if (img->buf) free (img->buf); free(img); } } unsigned char* imgGetBuffer(Image img) { if(img) return img->buf; else return NULL; } void imgDraw(Image img) { glDrawPixels (img->width, img->height, GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLubyte *) img->buf); } void imgClear(Image img) { int i, j, index; for(i=0; iwidth; i++) for(j=0; jheight; j++) { index = (j*img->width + i)*3; img->buf[index ] = 0; img->buf[index+1] = 0; img->buf[index+2] = 0; } } void imgGetDimensions(Image img, int *w, int *h) { if (w) *w = img->width; if (h) *h = img->height; } void imgSetPixel(Image img, int x, int y, unsigned char r, unsigned char g, unsigned char b) { int pos = (y*img->width*3) + (x*3); img->buf[pos+2] = r; img->buf[pos+1] = g; img->buf[pos ] = b; } void imgGetPixel(Image img, int x, int y, unsigned char *r, unsigned char *g, unsigned char *b) { int pos = (y*img->width*3) + (x*3); if (r) *r = img->buf[pos+2]; if (g) *g = img->buf[pos+1]; if (b) *b = img->buf[pos ]; } Image imgReadTGA (char *filename) { FILE *filePtr; Image image; /* imagem a ser criada */ unsigned char imageType; /* 2 para imagens BGR */ unsigned short int imageWidth; /* largura da imagem */ unsigned short int imageHeight; /* altura da imagem */ unsigned char bitCount; /* numero de bits por pixel */ unsigned char ucharSkip; /* dado lixo unsigned char */ short int sintSkip; /* dado lixo short int */ int nbp; /* numero de bytes por pixel */ long imageIdx; /* contadore de laco */ /* abre o arquivo com a imagem TGA */ filePtr = fopen(filename, "rb"); assert(filePtr); /* pula os primeiros dois bytes que devem ter valor zero */ ucharSkip = getc(filePtr); /* tamanho do descritor da imagem (0) */ if (ucharSkip != 0) printf("erro na leitura de %s: imagem com descritor\n", filename); ucharSkip = getc(filePtr); if (ucharSkip != 0) printf("erro na leitura de %s: imagem com tabela de cores\n", filename); /* le o tipo de imagem (que deve ser obrigatoriamente 2). Nao estamos tratando dos outros tipos */ imageType=getc(filePtr); assert(imageType == 2); /* pula 9 bytes relacionados com a tabela de cores (que nao existe quando a imagem e' RGBA, imageType=2) */ getuint((short unsigned int *)&sintSkip,filePtr); getuint((short unsigned int *)&sintSkip,filePtr); ucharSkip = getc(filePtr); /* especificacao da imagem */ getuint((short unsigned int *)&sintSkip,filePtr); /* origem em x (por default = 0) */ getuint((short unsigned int *)&sintSkip,filePtr); /* origem em y (por default = 0) */ getuint(&imageWidth,filePtr); /* largura */ getuint(&imageHeight,filePtr); /* altura */ /* read image bit depth */ bitCount=getc(filePtr); assert((bitCount == 32)||(bitCount == 24)); /* colorMode -> 4 = BGRA (32 bits) */ nbp = bitCount/8; /* numero de bytes por pixel */ /* read 1 byte of garbage data */ ucharSkip = getc(filePtr); /* cria uma instancia do tipo Imagem */ image = imgCreate(imageWidth,imageHeight); assert(image); for (imageIdx = 0; imageIdx < 3*imageWidth*imageHeight; imageIdx += 3) { image->buf[imageIdx+2] = (unsigned char) getc(filePtr); /* le B */ image->buf[imageIdx+1] = (unsigned char) getc(filePtr); /* le G */ image->buf[imageIdx ] = (unsigned char) getc(filePtr); /* le R */ if (nbp==4) ucharSkip = (unsigned char) getc(filePtr); } fclose(filePtr); return image; } int imgWriteTGA(char *filename, Image img) { unsigned char imageType=2; /* BGR sem compressão */ unsigned char bitDepth=24; /* 24 bits por pixel */ FILE *filePtr; /* ponteiro do arquivo */ unsigned char byteZero=0; /* usado para escrever um byte zero no arquivo */ short int shortZero=0; /* usado para escrever um short int zero no arquivo */ /* cria um arquivo binario novo */ filePtr = fopen(filename, "wb"); assert(filePtr); /* escreve o cabecalho */ putc(byteZero,filePtr); /* 0, no. de caracteres no campo de id da imagem */ putc(byteZero,filePtr); /* = 0, imagem nao tem palheta de cores */ putc(imageType,filePtr); /* = 2 -> imagem "true color" (BGR) */ putuint(shortZero,filePtr); /* info sobre a tabela de cores (inexistente) */ putuint(shortZero,filePtr); /* idem */ putc(byteZero,filePtr); /* idem */ putuint(shortZero,filePtr); /* =0 origem em x */ putuint(shortZero,filePtr); /* =0 origem em y */ putuint(img->width,filePtr); /* largura da imagem em pixels */ putuint(img->height,filePtr); /* altura da imagem em pixels */ putc(bitDepth,filePtr); /* numero de bits de um pixel */ putc(byteZero, filePtr); /* =0 origem no canto inf esquerdo sem entrelacamento */ /* escreve o buf de cores da imagem */ { int num_pixels = img->width*img->height; unsigned char* buf_aux = (unsigned char*) malloc(3*num_pixels); int i; for(i=0; ibuf[3*i+2]; buf_aux[3*i+1] = img->buf[3*i+1]; buf_aux[3*i+2] = img->buf[3*i ]; } fwrite(buf_aux, sizeof(unsigned char), 3*img->width*img->height, filePtr); free(buf_aux); } fclose(filePtr); return 1; } int imgWriteBMP(char *filename, Image img) { int width, height, size, i, result; unsigned char* r; unsigned char* g; unsigned char* b; unsigned char* imgBuf = imgGetBuffer(img); imgGetDimensions(img, &width, &height); size = width*height; r = (unsigned char*)malloc(size*sizeof(unsigned char)); g = (unsigned char*)malloc(size*sizeof(unsigned char)); b = (unsigned char*)malloc(size*sizeof(unsigned char)); for(i=0; iwidth =(unsigned int) w; stat->height =(unsigned int) h; stat->buf = (double *) malloc (w * h * 3 * sizeof(double)); assert(stat->buf); return stat; } void imgStatisticsDestroy (ImgStatistics stat) { if (stat) { if (stat->buf) free (stat->buf); free(stat); } } double* imgStatisticsGetBuffer(ImgStatistics stat) { if(stat) return stat->buf; else return NULL; } void imgStatisticsSetPixel(ImgStatistics stat, int x, int y, double r, double g, double b) { int pos = (y*stat->width*3) + (x*3); stat->buf[pos+2] = r; stat->buf[pos+1] = g; stat->buf[pos ] = b; } void imgStatisticsGetPixel(ImgStatistics stat, int x, int y, double *r, double *g, double *b) { int pos = (y*stat->width*3) + (x*3); if (r) *r = stat->buf[pos+2]; if (g) *g = stat->buf[pos+1]; if (b) *b = stat->buf[pos ]; } /* implementacao para video */ Sequence imgCreateSequence(int w, int h, int nframes) { Sequence seq; seq = (Sequence) malloc (sizeof(struct sequence_imp)); assert(seq); seq->nframes = nframes; seq->width =(unsigned int) w; seq->height =(unsigned int) h; seq->buf = (unsigned char *) malloc (nframes* w * h * 3); assert(seq->buf); return seq; } void imgDestroySequence (Sequence seq) { if (seq) { if (seq->buf) free (seq->buf); free(seq); } } unsigned char * imgGetFrameBuffer(Sequence seq, int frame_i) { return (seq->buf + frame_i*seq->width*seq->height*3); } Image imgAverage(Sequence seq) { int nf=seq->nframes; int w=seq->width; int h=seq->height; Image img=imgCreate(w,h); float r,g,b; int x,y,n; for (y=0;ybuf[pos ]; g+=seq->buf[pos+1]; r+=seq->buf[pos+2]; } r/=nf;g/=nf;b/=nf; imgSetPixel(img,x,y,(unsigned char)r,(unsigned char)g,(unsigned char)b); } } return img; } void imgGetStatistics(Sequence seq, Image avg, ImgStatistics std_dev, ImgStatistics avg_norm, ImgStatistics norm_std_dev) { int nf=seq->nframes; int w=seq->width; int h=seq->height; // Image img=imgCreate(w,h); unsigned char raux, gaux, baux; double rgbaux; double r, g, b, r2, g2, b2; double avg_r, avg_g, avg_b; double stddev_r, stddev_g, stddev_b; double nr, ng, nb, nr2, ng2, nb2; double avg_nr, avg_ng, avg_nb; double stddev_nr, stddev_ng, stddev_nb; int x,y,n; for (y=0;ybuf[pos+2]; gaux=seq->buf[pos+1]; baux=seq->buf[pos ]; r+=raux; g+=gaux; b+=baux; r2+=raux*raux; g2+=gaux*gaux; b2+=baux*baux; rgbaux = (double)raux + (double)gaux + (double)baux; if(rgbaux>0) { nr+=((double)raux)/rgbaux; ng+=((double)gaux)/rgbaux; nb+=((double)baux)/rgbaux; nr2+=(((double)raux)/rgbaux)*(((double)raux)/rgbaux); ng2+=(((double)gaux)/rgbaux)*(((double)gaux)/rgbaux); nb2+=(((double)baux)/rgbaux)*(((double)baux)/rgbaux); } } avg_r = r/nf; avg_g = g/nf; avg_b = b/nf; stddev_r = sqrt(r2/nf - avg_r*avg_r); stddev_g = sqrt(g2/nf - avg_g*avg_g); stddev_b = sqrt(b2/nf - avg_b*avg_b); avg_nr = nr/nf; avg_ng = ng/nf; avg_nb = nb/nf; stddev_nr = sqrt(nr2/nf - avg_nr*avg_nr); stddev_ng = sqrt(ng2/nf - avg_ng*avg_ng); stddev_nb = sqrt(nb2/nf - avg_nb*avg_nb); imgSetPixel(avg,x,y,(unsigned char)avg_r,(unsigned char)avg_g,(unsigned char)avg_b); imgStatisticsSetPixel(std_dev,x,y,stddev_r,stddev_g,stddev_b); imgStatisticsSetPixel(avg_norm,x,y,avg_nr,avg_ng,avg_nb); imgStatisticsSetPixel(norm_std_dev,x,y,stddev_nr,stddev_ng,stddev_nb); } } return; }