#include "stdio.h" #include "string.h" #include "stdlib.h" #include "bmp.h" 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, int size, int bigendian) { int i; unsigned int r=0,t; for(i=0;i>1; } return n; } 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); int theight=readhexint(data+8,4,1); if(theight<0) theight=-theight; else header->invertedlines=1; header->height=theight; 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; } int readPalette(int* palette, dataheader* dheader, FILE* img, fileheader* fheader) { int i,read=0; 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; read=fread(data,1,dheader->indexedcolors*colorsize,img); for(i=0;iindexedcolors;i++) palette[i]=readhexint(data+i*colorsize,3,1); free(data); return read==dheader->indexedcolors*colorsize; } void setImgPixel(byte* image, int y, int x, byte color, dataheader* dheader) { int offset=(y*dheader->width+x)/8; if(dheader->invertedlines) offset=((dheader->height-1-y)*dheader->width+x)/8; byte oldcolor=image[offset]; if(color) oldcolor|=1<<(7-(x%8)); else oldcolor&=~(1<<(7-(x%8))); image[offset]=oldcolor; } int readRLEImage(byte* image, dataheader* dheader, int* palette, FILE* img) { //memset(image,0,dheader->width*dheader->height); byte* rawdatabuf = (byte*) malloc(dheader->sourcedatasize); if(!rawdatabuf) return 0; 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; int n = 8/dheader->bits, t; if(!n) n=1; unsigned int* 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]; setImgPixel(image,y,x,color,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]; tmp[j]=color; } 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(byte* image, dataheader* dheader, int* palette, FILE* img) { int i,j; byte* rawdatabuf = (byte*) malloc(dheader->sourcedatasize); if(!rawdatabuf) return 0; if( fread(rawdatabuf, 1, dheader->sourcedatasize, img)==dheader->sourcedatasize ) { unsigned int color, data; 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]; setImgPixel(image,i,j,color,dheader); } } } free(rawdatabuf); return 1; } int readImage(byte* image, dataheader* dheader, int* palette, FILE* img, fileheader* fheader) { if(fheader->type==1 && dheader->compression==0) return readRAWImage(image,dheader,palette,img); if(fheader->type==1 && dheader->compression==1) return readRLEImage(image,dheader,palette,img); return 0; }