#include "fxlib.h" #include "image.h" int nbbits(unsigned int mask) { int n=0; while(mask) { if(mask&1) n++; mask=mask>>1; } return n; } unsigned int maskright(unsigned int data, unsigned int mask) { data=data&mask; while(mask && !(mask&1)) { data=data>>1; mask=mask>>1; } return data; } unsigned int readhexint(unsigned char* buf, unsigned long int size, int bigendian) { int i; unsigned int r=0,t; for(i=0;itype=1; header->size=MAX_FILEHEADER_SIZE; } } if(header->type) read+=Bfile_ReadFile(file, data+read, header->size-read,read); return header->type && read==header->size; } int readDataHeader(dataheader* header, int file, fileheader* fheader) { unsigned char data[MAX_DATAHEADER_SIZE]; int read=0; int valid=0; memset(header,0,sizeof(dataheader)); if(fheader->type==1) { read+=Bfile_ReadFile(file,data,4, -1); header->invertedlines=0; if(read==4) { header->size=readhexint(data,4,1); if(header->size<=MAX_DATAHEADER_SIZE) { read+=Bfile_ReadFile(file,data+read,header->size-read,-1); 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->width%(8/header->bits)) header->rawlinesize++; 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(header->bits>=24 || header->bits<=8) header->redmask=0x00FF0000; if(header->bits==16) header->redmask=0x00007C00; if(header->bits>=24 || header->bits<=8) header->greenmask=0x0000FF00; if(header->bits==16) header->greenmask=0x000003E0; if(header->bits>=24 || header->bits<=8) header->bluemask=0x000000FF; if(header->bits==16) header->bluemask=0x0000001F; if(read>=44) if(memcmp(data+40,"BGRs") && memcmp(data+40,"Win")) { if(read>=44) header->redmask=readhexint(data+40,4,1); if(read>=48) header->greenmask=readhexint(data+44,4,1); if(read>=52) header->bluemask=readhexint(data+48,4,1); } 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; } unsigned char makeData(int color,dataheader* dheader) { unsigned char data; unsigned int r=maskright(color,dheader->redmask); unsigned int g=maskright(color,dheader->greenmask); unsigned int b=maskright(color,dheader->bluemask); unsigned int a=maskright(color,dheader->alphamask); int sr=(dheader->redbits-8); int sg=(dheader->greenbits-8); int sb=(dheader->bluebits-8); unsigned int alphamax=maskright(dheader->alphamask,dheader->alphamask); if(sr>0) r=r>>sr; if(sg>0) g=g>>sg; if(sb>0) b=b>>sb; if(sr<0) r=r<<(-sr); if(sg<0) g=g<<(-sg); if(sb<0) b=b<<(-sb); data=(((r*30+g*59+b*11)/100)); //Print("*");PrintN(data);Print("*"); data=data/(1<<(8-min(dheader->bits,2))); return data; } #define MAX_PALETTE 256 unsigned char palette[MAX_PALETTE]; unsigned char* readPalette(dataheader* dheader, int file, fileheader* fheader) { int i; unsigned int color; // unsigned char* palette; int colorsize = 4; // OS2 BITMAPCOREHEADER -> palette sur 3 octets if(fheader->type==1 && dheader->size==12) colorsize=3; // palette=(unsigned char*) malloc(dheader->indexedcolors*colorsize); Bfile_ReadFile(file,palette,dheader->indexedcolors*colorsize,-1); for(i=0;iindexedcolors;i++) { color=readhexint(palette+i*colorsize,3,1); //locate(3,3); //PrintN(i);Print("|"); //PrintN(color);Print("|"); palette[i]=makeData(color,dheader); //PrintN(palette[i]);Print("|"); //WaitKey(); } // palette=(unsigned char*)realloc(palette,dheader->indexedcolors); return palette; } unsigned char getImgPixel(unsigned char* image, int y, int x, dataheader* dheader) { unsigned int i; unsigned char color; if(dheader->invertedlines) y=dheader->height-1-y; i = y*dheader->width+x; if(dheader->bits==1) { color=image[i/8]; color=(color&(1<<(i%8)))>>(i%8); } else { color=image[i/4]; color=(color&(3<<(2*(i%4))))>>(2*(i%4)); } return color; } void setImgPixel(unsigned char* image, int y, int x, unsigned char color, dataheader* dheader) { unsigned int i = y*dheader->width+x; unsigned char ocolor; if(dheader->bits==1) { ocolor=image[i/8]; ocolor=(ocolor&~(1<<(i%8)))|(color<<(i%8)); image[i/8]=ocolor; } else { ocolor=image[i/4]; ocolor=(ocolor&~(3<<(2*(i%4))))|(color<<(2*(i%4))); image[i/4]=ocolor; } } unsigned char* readRAWImage(dataheader* dheader, unsigned char* palette, int file) { unsigned long int i,j; int size2=dheader->width*dheader->height/((dheader->bits==1)?8:4)+1,size=dheader->sourcedatasize; unsigned char* image = (unsigned char*) malloc(max(size2,size)); unsigned char mask; if(!image) return 0; if( Bfile_ReadFile(file, image, dheader->sourcedatasize, -1)==dheader->sourcedatasize ) { unsigned int color,colorbyte; int pixbytes; // bytes to read for each pixel if(dheader->bits<8) pixbytes=1; else pixbytes=dheader->bits/8; for (i = 0; i < dheader->height; i++) { mask=0; for(j=0; j < dheader->width; j++) { if(!(j%(8/dheader->bits))) colorbyte=readhexint(image+i*dheader->rawlinesize+dheader->bits*j/8,pixbytes,1); color=colorbyte; locate(2,2); //PrintN(i);Print(" "); //PrintN(j);Print("|"); //PrintN(color);Print("|"); 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); } //PrintN(color);Print(" "); if(dheader->indexedcolors) color=palette[color]; //PrintN(color);Print(" "); //WaitKey(); setImgPixel(image,i,j,color,dheader); } } } image = (unsigned char*)realloc(image,size2); return image; } unsigned char* readRLEImage(dataheader* dheader, int* palette, int file) { int size2=dheader->width*dheader->height/((dheader->bits==1)?8:4)+1,size=dheader->sourcedatasize; unsigned char* image = (unsigned char*) malloc(size2); unsigned char* rawdatabuf = (unsigned char*) malloc(dheader->sourcedatasize); unsigned int i=0,j,y=0,x=0, stop=0; unsigned int* tmp; if(!rawdatabuf || !image) return 0; if( Bfile_ReadFile(file, image, dheader->sourcedatasize, -1)==dheader->sourcedatasize ) { unsigned int color, ccolor, data; int n = 8/dheader->bits, t; if(!n) n=1; tmp = (unsigned int*) malloc(n*sizeof(unsigned int)); if(tmp) { 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++; } 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]; data = makeData(color,dheader); 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]; data = makeData(color,dheader); 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 image; } unsigned char* readImage(dataheader* dheader, unsigned char* palette, int file, fileheader* fheader) { if(fheader->type==1 && dheader->compression==0) return readRAWImage(dheader,palette,file); if(fheader->type==1 && dheader->compression==1) return readRLEImage(dheader,palette,file); return 0; }