ついでにカラーテーブルの色のうち、使っていない色を削ります。
いじめないでください。(変なBMPを与えたりしないでください)
無保証です。バグがあるかもしれません。
#include
#include
typedef struct {
char bfType[2];
unsigned int bfSize;
short bfReserved1;
short bfReserved2;
unsigned int bfOffBits;
} bmpHeader_t;
typedef struct {
unsigned int biSize;
unsigned int biWidth;
unsigned int biHeight;
unsigned int biPlanes;
unsigned int biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
unsigned int biXPelsPerMeter;
unsigned int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} bmpInfoHeader_t;
void char2bmpHeader(const unsigned char* in,bmpHeader_t* out) {
out->bfType[0]=in[0];
out->bfType[1]=in[1];
out->bfSize=in[2]|(in[3]bfReserved1=in[6]|(in[7]bfReserved2=in[8]|(in[9]bfOffBits=in[10]|(in[11]bfType[0];
out[1]=in->bfType[1];
out[2]=(in->bfSize)&0xFF;out[3]=(in->bfSize>>8)&0xFF;
out[4]=(in->bfSize>>16)&0xFF;out[5]=(in->bfSize>>24)&0xFF;
out[6]=(in->bfReserved1)&0xFF;out[7]=(in->bfReserved1>>8)&0xFF;
out[8]=(in->bfReserved2)&0xFF;out[9]=(in->bfReserved2>>8)&0xFF;
out[10]=(in->bfOffBits)&0xFF;out[11]=(in->bfOffBits>>8)&0xFF;
out[12]=(in->bfOffBits>>16)&0xFF;out[13]=(in->bfOffBits>>24)&0xFF;
}
void char2bmpInfoHeader(const unsigned char* in,bmpInfoHeader_t* out) {
out->biSize=in[0]|(in[1]biWidth=in[4]|(in[5]biHeight=in[8]|(in[9]biPlanes=in[12]|(in[13]biBitCount=in[14]|(in[15]biCompression=in[16]|(in[17]biSizeImage=in[20]|(in[21]biXPelsPerMeter=in[24]|(in[25]biYPelsPerMeter=in[28]|(in[29]biClrUsed=in[32]|(in[33]biSize)&0xFF;out[1]=(in->biSize>>8)&0xFF;
out[2]=(in->biSize>>16)&0xFF;out[3]=(in->biSize>>24)&0xFF;
out[4]=(in->biWidth)&0xFF;out[5]=(in->biWidth>>8)&0xFF;
out[6]=(in->biWidth>>16)&0xFF;out[7]=(in->biWidth>>24)&0xFF;
out[8]=(in->biHeight)&0xFF;out[9]=(in->biHeight>>8)&0xFF;
out[10]=(in->biHeight>>16)&0xFF;out[11]=(in->biHeight>>24)&0xFF;
out[12]=(in->biPlanes)&0xFF;out[13]=(in->biPlanes>>8)&0xFF;
out[14]=(in->biBitCount)&0xFF;out[15]=(in->biBitCount>>8)&0xFF;
out[16]=(in->biCompression)&0xFF;out[17]=(in->biCompression>>8)&0xFF;
out[18]=(in->biCompression>>16)&0xFF;out[19]=(in->biCompression>>24)&0xFF;
out[20]=(in->biSizeImage)&0xFF;out[21]=(in->biSizeImage>>8)&0xFF;
out[22]=(in->biSizeImage>>16)&0xFF;out[23]=(in->biSizeImage>>24)&0xFF;
out[24]=(in->biXPelsPerMeter)&0xFF;out[25]=(in->biXPelsPerMeter>>8)&0xFF;
out[26]=(in->biXPelsPerMeter>>16)&0xFF;out[27]=(in->biXPelsPerMeter>>24)&0xFF;
out[28]=(in->biYPelsPerMeter)&0xFF;out[29]=(in->biYPelsPerMeter>>8)&0xFF;
out[30]=(in->biYPelsPerMeter>>16)&0xFF;out[31]=(in->biYPelsPerMeter>>24)&0xFF;
out[32]=(in->biClrUsed)&0xFF;out[33]=(in->biClrUsed>>8)&0xFF;
out[34]=(in->biClrUsed>>16)&0xFF;out[35]=(in->biClrUsed>>24)&0xFF;
out[36]=(in->biClrImportant)&0xFF;out[37]=(in->biClrImportant>>8)&0xFF;
out[38]=(in->biClrImportant>>16)&0xFF;out[39]=(in->biClrImportant>>24)&0xFF;
}
unsigned int compressBmpLine(
const unsigned char* in,unsigned char* out,unsigned int width) {
unsigned int i,j;
unsigned int width2=(width+1)/2;
unsigned int outputSize;
unsigned int continueNum;
unsigned int lastNumPosition;
int isSameMode;
if(width==0) {
out[0]=0x00;out[1]=0x00;
return 2;
}
if(width=2) {
if(isSameMode) {
lastNumPosition=outputSize;
out[outputSize++]=continueNum*2;
out[outputSize++]=in[i-1];
} else {
out[outputSize++]=0x00;
lastNumPosition=outputSize;
out[outputSize++]=continueNum*2;
for(j=i-continueNum;j \n");
return 0;
}
/* 入力ファイルの読み込み */
fp=fopen(argv[1],"rb");
readSize=fread(bmpHeaderData,sizeof(char),14,fp);
if(readSize!=14) {
fprintf(stderr,"File size error\n");fclose(fp);return 1;
}
readSize=fread(bmpInfoHeaderData,sizeof(char),40,fp);
if(readSize!=40) {
fprintf(stderr,"File size error\n");fclose(fp);return 1;
}
char2bmpHeader(bmpHeaderData,&bmpHeader);
char2bmpInfoHeader(bmpInfoHeaderData,&bmpInfoHeader);
if(bmpHeader.bfType[0]!='B' || bmpHeader.bfType[1]!='M') {
fprintf(stderr,"Not bitmap file\n");fclose(fp);return 1;
}
if(bmpInfoHeader.biSize!=0x28) {
fprintf(stderr,"Strange header size\n");fclose(fp);return 1;
}
if(bmpInfoHeader.biPlanes!=1 || bmpInfoHeader.biBitCount!=4) {
fprintf(stderr,"Unsupported type\n");fclose(fp);return 1;
}
if(bmpInfoHeader.biClrUsed>16) {
fprintf(stderr,"Strange color number\n");fclose(fp);return 1;
}
if(bmpInfoHeader.biCompression!=0) {
fprintf(stderr,"Already Compressed\n");fclose(fp);return 1;
}
lineOffset=((((bmpInfoHeader.biWidth+1)/2)+3)/4)*4;
inputDataSize=lineOffset*bmpInfoHeader.biHeight;
if(bmpInfoHeader.biSizeImage>0 &&
bmpInfoHeader.biSizeImage!=inputDataSize) {
fprintf(stderr,"Strange data size\n");fclose(fp);return 1;
}
if(bmpInfoHeader.biClrUsed==0)bmpInfoHeader.biClrUsed=16;
readSize=fread(bmpColorData,sizeof(char),bmpInfoHeader.biClrUsed*4,fp);
if(readSize!=bmpInfoHeader.biClrUsed*4) {
fprintf(stderr,"File size error\n");fclose(fp);return 1;
}
inputFileSize=14+40+bmpInfoHeader.biClrUsed*4+inputDataSize;
if(bmpHeader.bfSize!=inputFileSize ||
bmpHeader.bfOffBits!=14+40+bmpInfoHeader.biClrUsed*4) {
fprintf(stderr,"Strange offset or size\n");fclose(fp);return 1;
}
bmpData=malloc(inputDataSize);
bmpDataAfter=malloc(inputDataSize*3);
if(bmpData==NULL || bmpDataAfter==NULL) {
if(bmpData)free(bmpData);
if(bmpDataAfter)free(bmpDataAfter);
fprintf(stderr,"Memory allocate error\n");fclose(fp);return 1;
}
readSize=fread(bmpData,sizeof(char),inputDataSize,fp);
if(readSize!=inputDataSize) {
free(bmpData);free(bmpDataAfter);
fprintf(stderr,"File size error\n");fclose(fp);return 1;
}
fclose(fp);
/* カラーテーブルの最適化 */
for(i=0;i>(j%2?0:4))&0xF;
usedFlag[nowColor]=1;
}
}
bmpInfoHeader.biClrUsed=0;
for(i=0;i>(j%2?0:4))&0xF;
if(j%2==0) {
bmpData[i*lineOffset+j/2]=
(bmpData[i*lineOffset+j/2]&0x0F)|((usedFlag[nowColor]-1) %u (%5.2f%%)\n",
inputFileSize,outputFileSize,
(double)outputFileSize*100.0/inputFileSize);
return 0;
}