みけCATのにっき(仮)
つれづれなるまゝに、日くらし、PCにむかひて、心に移りゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
(本当か!?)
出典

16色ビットマップファイルの圧縮

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

16色ビットマップファイルの圧縮

投稿記事 by みけCAT » 13年前

16色の無圧縮BMPファイルをRLE圧縮したBMPファイルに変換するプログラムです。
ついでにカラーテーブルの色のうち、使っていない色を削ります。
いじめないでください。(変なBMPを与えたりしないでください)
無保証です。バグがあるかもしれません。

CODE:

#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;
}
プログラムは添付もしました。
添付ファイル

[拡張子 zip は無効化されているため、表示できません]


コメントはまだありません。