#include "image.h" #include "console.h" #include "tools.h" #include "charmap.h" void dispHeader(fileheader* fheader, dataheader* header) { if(!fheader->type) displn("Type: unknown",0); else { if(fheader->type==1) { displn("Type : BMP",0); } if(fheader->type) { disp("File Header size: ",0); dispi(fheader->size,0); displn("",0); disp("Data Header size: ",0); dispi(header->size,0); displn("",0); disp("Width : ",0); dispi(header->width,0); displn("",0); disp("Height : ",0); dispi(header->height,0); displn("",0); disp("Planes : ",0); dispi(header->planes,0); displn("",0); disp("Bits : ",0); dispi(header->bits,0); displn("",0); disp("Compression : ",0); if(!header->compression) displn("none",0); else if(header->compression==1) displn("RLE",0); else displn("unknown",0); disp("Data size : ",0); dispi(header->sourcedatasize,0); displn("",0); disp("Indexed colors : ",0); dispi(header->indexedcolors,0); displn("",0); disp("Red Mask : ",0); dispi(header->redmask,0); displn("",0); disp("Green Mask : ",0); dispi(header->greenmask,0); displn("",0); disp("Blue Mask : ",0); dispi(header->bluemask,0); displn("",0); disp("Alpha Mask : ",0); dispi(header->alphamask,0); displn("",0); disp("Red Bits : ",0); dispi(header->redbits,0); displn("",0); disp("Green Bits : ",0); dispi(header->greenbits,0); displn("",0); disp("Blue Bits : ",0); dispi(header->bluebits,0); displn("",0); disp("Alpha Bits : ",0); dispi(header->alphabits,0); displn("",0); } } } int readFileHeader(fileheader* header, FILE* file) { unsigned char data[MAX_FILEHEADER_SIZE]; memset(header,0,sizeof(fileheader)); int read=0; read+=fread(data, 1, 2, file); if(read==2) { int magic2=readhexint(data,2,0); if( magic2==0x424D || magic2==0x4241 || magic2==0x4349 || magic2==0x4350 || magic2==0x4943 || magic2==0x5054 ) { header->type=1; header->size=14; } } if(header->type) read+=fread(data+read,1,header->size-read,file); return header->type && read==header->size; } int readDataHeader(dataheader* header, FILE* file, fileheader* fheader) { unsigned char data[MAX_DATAHEADER_SIZE]; memset(header,0,sizeof(dataheader)); int read=0; int valid=0; if(fheader->type==1) { read+=fread(data,1,4,file); header->invertedlines=1; if(read==4) { header->size=readhexint(data,4,1); if(header->size<=MAX_DATAHEADER_SIZE) { read+=fread(data+read,1,header->size-read,file); if(read>=40) { header->width=readhexint(data+4,4,1); header->height=readhexint(data+8,4,1); if(header->height<0) header->height=-header->height; else header->invertedlines=1; header->planes=readhexint(data+12,2,1); header->bits=readhexint(data+14,2,1); header->compression=readhexint(data+16,4,1); // 0 = none // 1 = RLE 8-bits // 2 = RLE 4-bits // 3 = compression Huffman1D si le header est un BITMAPCOREHEADER2 // sinon, compression par utilisation de bitmask, ce qui est géré par défaut // 4 = JPEG (dans un BMP ? . . .) // 5 = PNG (dans un BMP ? . . .) if(header->compression==3 && header->size!=64) header->compression=0; if(header->compression==2) header->compression=1; header->rawlinesize=header->bits*header->width/8; if(fheader->type==1) // padding pour les BMP if(header->rawlinesize%4) header->rawlinesize+=4-(header->rawlinesize%4); if(!header->compression) { header->sourcedatasize=header->rawlinesize*header->height; } else header->sourcedatasize=readhexint(data+20,4,1); if(header->bits<=8) // présence d'une palette { header->indexedcolors=readhexint(data+32,4,1); if(!header->indexedcolors) header->indexedcolors=1<bits; } if(read>=44) header->redmask=readhexint(data+40,4,1); else { if(header->bits>=24 || header->bits<=8) header->redmask=0x00FF0000; if(header->bits==16) header->redmask=0x00007C00; } if(read>=48) header->greenmask=readhexint(data+44,4,1); else { if(header->bits>=24 || header->bits<=8) header->greenmask=0x0000FF00; if(header->bits==16) header->greenmask=0x000003E0; } if(read>=52) header->bluemask=readhexint(data+48,4,1); else { if(header->bits>=24 || header->bits<=8) header->bluemask=0x000000FF; if(header->bits==16) header->bluemask=0x0000001F; } if(read>=56) header->alphamask=readhexint(data+52,4,1); else if(header->bits==32) header->alphamask=0xFF000000; header->redbits=nbbits(header->redmask); header->greenbits=nbbits(header->greenmask); header->bluebits=nbbits(header->bluemask); header->alphabits=nbbits(header->alphamask); valid=1; } } } } return valid && read==header->size; } void readPalette(int* palette, dataheader* dheader, FILE* img, fileheader* fheader) { int i; unsigned char* data; data=(unsigned char*) malloc(dheader->indexedcolors*4); int colorsize = 4; // OS2 BITMAPCOREHEADER -> palette sur 3 octets if(fheader->type==1 && dheader->size==12) colorsize=3; fread(data,1,dheader->indexedcolors*colorsize,img); for(i=0;iindexedcolors;i++) palette[i]=readhexint(data+i*colorsize,3,1); free(data); } void setImgPixel(unsigned char* image, int y, int x, int color, dataheader* dheader) { if(dheader->invertedlines) image[(dheader->height-1-y)*dheader->width+x]=color; else image[y*dheader->width+x]=color; } int px=-1,py=-1; void initImgProgress(int x, int y, int p) { px=x; py=y; drwStr((x+3)*CHAR_WIDTH,y*CHAR_HEIGHT,"%",0); updateProgress(p); } void updateProgress(int p) { char tmp[4]; itoa(tmp,p,10); drwStr(px*CHAR_WIDTH,py*CHAR_HEIGHT,tmp,0); } void endImgProgress() { px=-1; py=-1; } int readRLEImage(unsigned char* image, dataheader* dheader, int* palette, FILE* img, fileheader* fheader) { //memset(image,0,dheader->width*dheader->height); unsigned char* rawdatabuf = (char*) malloc(dheader->sourcedatasize); unsigned int i=0,j,y=0,x=0, stop=0; if( fread(rawdatabuf, 1, dheader->sourcedatasize, img)==dheader->sourcedatasize ) { unsigned int color, ccolor, data; unsigned int red,blue,green,alpha; int n = 8/dheader->bits, t; if(!n) n=1; unsigned int* tmp = (unsigned int*) malloc(n*sizeof(unsigned int)); int nsredfactor=1<<(dheader->redbits-5); // facteur de conversion sur 4-bits pour écran Nspire int nsgreenfactor=1<<(dheader->greenbits-5); // facteur de conversion sur 4-bits pour écran Nspire int nsbluefactor=1<<(dheader->bluebits-5); // facteur de conversion sur 4-bits pour écran Nspire unsigned int alphamax=maskright(dheader->alphamask,dheader->alphamask); unsigned char mask=0; int pixbytes; // bytes to read for each pixel if(dheader->bits<8) pixbytes=1; else pixbytes=dheader->bits/8; while(!stop && isourcedatasize && yheight) { if(rawdatabuf[i]==0) { if(rawdatabuf[i+1]==0) { x=0;y++; if(py>=0) updateProgress(y*100/dheader->height);} else if(rawdatabuf[i+1]==1) stop=1; else if(rawdatabuf[i+1]==2) { x+=rawdatabuf[i+2]; y+=rawdatabuf[i+3]; } else { mask=0; for(j=0;jbits/8,pixbytes,1); if(dheader->bits<8) //rotation du masque de lecture pour les données de moins de 8-bits { mask=mask>>dheader->bits; if(!mask) mask=(~0)<<(8-dheader->bits); color=maskright(color,mask); } if(dheader->indexedcolors) color=palette[color]; red=maskright(color,dheader->redmask); green=maskright(color,dheader->greenmask); blue=maskright(color,dheader->bluemask); alpha=maskright(color,dheader->alphamask); data=(int)(red/nsredfactor*.3F+green/nsgreenfactor*.59F+blue/nsbluefactor*.11F); if(alphamax) data=16-((16-data)*alpha/alphamax); setImgPixel(image,y,x,data,dheader); x++; } t=rawdatabuf[i+1]%(16/dheader->bits); if(dheader->bits<=8 && t) { i+=(rawdatabuf[i+1]+16/dheader->bits-t)*dheader->bits/8; } else i+=rawdatabuf[i+1]*dheader->bits/8; } i+=2; } else { ccolor=readhexint(rawdatabuf+i+1,pixbytes,1); color=ccolor; mask=(~0)<<(8-dheader->bits); for(j=0;jbits<8) //rotation du masque de lecture pour les données de moins de 8-bits { color=maskright(ccolor,mask); mask=mask>>dheader->bits; } if(dheader->indexedcolors) color=palette[color]; red=maskright(color,dheader->redmask); green=maskright(color,dheader->greenmask); blue=maskright(color,dheader->bluemask); alpha=maskright(color,dheader->alphamask); data=(int)(red/nsredfactor*.3F+green/nsgreenfactor*.59F+blue/nsbluefactor*.11F); if(alphamax) data=32-((32-data)*alpha/alphamax); tmp[j]=data; } for(j=0;jsourcedatasize-1) { if(rawdatabuf[i]==0 && rawdatabuf[i+1]==1) { stop=1; if(isourcedatasize-1) i+=2; if(yheight) y++; } } if(yheight && isourcedatasize-1) { if(rawdatabuf[i]==0 && rawdatabuf[i+1]==0) { x=0; if(isourcedatasize-1) i+=2; if(yheight) y++; } } free(rawdatabuf); return stop && i==dheader->sourcedatasize; } int readRAWImage(unsigned char* image, dataheader* dheader, int* palette, FILE* img, fileheader* fheader) { int i,j; unsigned char* rawdatabuf = (char*) malloc(dheader->sourcedatasize); if( fread(rawdatabuf, 1, dheader->sourcedatasize, img)==dheader->sourcedatasize ) { unsigned int color, data; unsigned int red,blue,green,alpha; int nsredfactor=1<<(dheader->redbits-5); // -4 facteur de conversion sur 4-bits pour écran Nspire int nsgreenfactor=1<<(dheader->greenbits-5); // -4 facteur de conversion sur 4-bits pour écran Nspire int nsbluefactor=1<<(dheader->bluebits-5); // -4 facteur de conversion sur 4-bits pour écran Nspire unsigned int alphamax=maskright(dheader->alphamask,dheader->alphamask); int pixbytes; // bytes to read for each pixel if(dheader->bits<8) pixbytes=1; else pixbytes=dheader->bits/8; unsigned char mask=0; for (i = 0; i < dheader->height; i++) { for(j=0; j < dheader->width; j++) { color=readhexint(rawdatabuf+dheader->rawlinesize*i+dheader->bits*j/8,pixbytes,1); if(dheader->bits<8) //rotation du masque de lecture pour les données de moins de 8-bits { mask=mask>>dheader->bits; if(!mask) mask=(~0)<<(8-dheader->bits); color=maskright(color,mask); } if(dheader->indexedcolors) color=palette[color]; red=maskright(color,dheader->redmask); green=maskright(color,dheader->greenmask); blue=maskright(color,dheader->bluemask); alpha=maskright(color,dheader->alphamask); data=(int)(red/nsredfactor*.3F+green/nsgreenfactor*.59F+blue/nsbluefactor*.11F); if(alphamax) data=32-((32-data)*alpha/alphamax); setImgPixel(image,i,j,data,dheader); } if(py>=0) updateProgress(i*100/dheader->height); } } free(rawdatabuf); return 1; } int readImage(unsigned char* image, dataheader* dheader, int* palette, FILE* img, fileheader* fheader) { if(dheader->compression==0) return readRAWImage(image,dheader,palette,img,fheader); if(dheader->compression==1) return readRLEImage(image,dheader,palette,img,fheader); return 0; }