ツムラ_メモ

大失敗を繰り返す。

画像からアスキーアート作成


超適当なソース.汚すぎるけれど,バックアップとして置いておく.
しばらく全くC言語に触れない生活していたせいもあってか,最悪の出来だ.
WindowsV4以外のBMPファイルを正常に処理できるかどうか不明.
ファイルの読み込み,書き込みが激しく無駄.
一度に読み書きしてディスクアクセスを低減させるべき.

入力されたBMP画像をグレイスケール・モノクロのBMP画像として出力 or 文字列として出力.
文字列の出力は現状1pixelが1文字という適当さ.

第一引数 入力BMPファイル名
第二引数 出力ファイル名
第三引数 処理タイプ 'gray'(グレイスケール) 'mono' (二値化) 'aa'(文字列化)
(第四引数 monoの場合のみ必要.二値化の場合の閾値)

C Language Exercise
FileReader=44Byte
test13.bmp load Success
w.txt Write Success
MagicNumber 0x4d42(BM)
FileSize 78294 Byte
offset 0x36
HeaderSize: 40 Byte
Width 159 pixel
Height 163 pixel
Color Planes 1
bit Per Pixel 24
compressionMethod 0
BMP Header Type: Windows V3
x:163,y:159
Success allocating memory:311004 Byte
null Byte :3 Byte


画像は出力結果をファイルにリダイレクトしてFirefoxで表示したもの.
横に159文字,縦に163文字表示できないと全体像が判らないっつー.

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#define MAX 10
#define SMAX 65536
typedef struct FReader{
	FILE *fi;
	unsigned int inbuf[MAX];
}FileReader;
typedef struct pixel{
	int r;
	int g;
	int b;
}Pixel;
typedef struct bmpFileHeader{
	unsigned magicNumber:16;
	unsigned fileSize:32;
	unsigned reserved:16;
	unsigned reserved2:16;
	unsigned offset:32;
}BMPFileHeader;
typedef struct dimh{	//DIM Header
	//unsigned size:2;
	unsigned headerSize:32;
	unsigned width:32;
	unsigned height:32;
	unsigned colorPlanes:16;
	unsigned bitPerPixel:16; //0,1,4,8,16,24,32 
	unsigned compressionMethod:32;
	unsigned imageSize:32;
	unsigned horizonalResolution:32;
	unsigned verticalResolution:32;
	unsigned colors:32;
	unsigned importantColors:32;
}Dimh;
unsigned int getValue(FileReader *fr, long position, int size){
	fseek(fr->fi,position,SEEK_SET);
	int bufc=0;
	bufc=fread(fr->inbuf, size, 1,fr->fi); 
	return fr->inbuf[bufc-1];
}
void getBMPFileHeader(BMPFileHeader *fh, FileReader *fr){
	unsigned int temp[10];
	fseek(fr->fi,0,SEEK_SET);
	fread(temp,2,1,fr->fi); fh->magicNumber=temp[0];
	fread(temp,4,1,fr->fi); fh->fileSize=temp[0];
	fread(temp,2,1,fr->fi); fh->reserved=temp[0];
	fread(temp,2,1,fr->fi); fh->reserved2=temp[0];
	fread(temp,4,1,fr->fi); fh->offset=temp[0];
	return;
}
void getDIMHeaderV3(Dimh *fd, FileReader *fr){
	unsigned int temp[10];
	fseek(fr->fi,14,SEEK_SET);
	fread(temp,4,1,fr->fi); fd->headerSize=temp[0];
	fread(temp,4,1,fr->fi); fd->width=temp[0];
	fread(temp,4,1,fr->fi); fd->height=temp[0];
	fread(temp,2,1,fr->fi); fd->colorPlanes=temp[0];
	fread(temp,2,1,fr->fi); fd->bitPerPixel=temp[0];
	fread(temp,4,1,fr->fi); fd->compressionMethod=temp[0];
	fread(temp,4,1,fr->fi); fd->imageSize=temp[0];
	fread(temp,4,1,fr->fi); fd->horizonalResolution=temp[0];
	fread(temp,4,1,fr->fi); fd->verticalResolution=temp[0];
	fread(temp,4,1,fr->fi); fd->colors=temp[0];
	fread(temp,4,1,fr->fi); fd->importantColors=temp[0];
	return;
}
void showBMPFileHeader(BMPFileHeader *fh){
	printf("MagicNumber\t\t0x%x(%c%c)\n",fh->magicNumber,fh->magicNumber,fh->magicNumber>>8);
	printf("FileSize\t\t%d Byte\n",fh->fileSize);
	printf("offset\t\t\t0x%x\n",fh->offset);
	return;
}
void showDIMHeaderV3(Dimh *fd){
	printf("HeaderSize:\t\t%d Byte\n",fd->headerSize);
	printf("Width\t\t\t%d pixel\n",fd->width);
	printf("Height\t\t\t%d pixel\n",fd->height);
	printf("Color Planes\t\t%d\n",fd->colorPlanes);
	printf("bit Per Pixel\t\t%d\n",fd->bitPerPixel);
	printf("compressionMethod\t%d\n",fd->compressionMethod);
	return;
}
int getInfomationHeader(FileReader *fr, Dimh *fd){
	int HeaderType=0;
	char type[256];
	HeaderType=getValue(fr,14,4);
	switch(HeaderType){
		case 40:
			strcpy(type,"Windows V3");
			getDIMHeaderV3(fd,fr);
			showDIMHeaderV3(fd);
			break;
		case 108:
			strcpy(type,"Windows V4");
			break;
		case 124:
			strcpy(type,"Windows V5");
			break;
		case 12:
			strcpy(type,"OS/2 V1");
			break;
		case 64:
			strcpy(type,"OS/2 V2");
			break;
		default:
			break;
	}
	printf("BMP Header Type:\t%s\n",type);
	return HeaderType;
}
Pixel *picP(Pixel *pic,int x,int y,int ysize){
	return pic + ( x * ysize) +y;
}
int getGrayscale(Pixel *pic,int x,int y,int ysize){
	int r,g,b;
	r=picP(pic,x,y,ysize)->r;
	g=picP(pic,x,y,ysize)->g;
	b=picP(pic,x,y,ysize)->b; 
	return 0.298912 * r + 0.586611 * g + 0.114478 * b;
}
unsigned int getPixel(Pixel *pic,int x,int y,int ysize){
	Pixel *temp;
	temp=picP(pic,x,y,ysize);
	return (temp->r << 16 ) | (temp->g << 8 ) | temp->b ;
}
unsigned int getPixelR(Pixel *pic,int x,int y,int ysize){
	return picP(pic,x,y,ysize)->r;
}
unsigned int getPixelG(Pixel *pic,int x,int y,int ysize){
	return picP(pic,x,y,ysize)->g;
}
unsigned int getPixelB(Pixel *pic,int x,int y,int ysize){
	return picP(pic,x,y,ysize)->b;
}
void setMemoryPixel(Pixel *pic,unsigned int value,int x,int y,int ysize){
	(pic + (x * ysize) + y)->r = (value & 0xff0000)>>16;
	(pic + (x * ysize) + y)->g = (value & 0x00ff00)>>8;
	(pic + (x * ysize) + y)->b = value & 0x0000ff;
	return; 
}
void setBMPFileHeader(BMPFileHeader *fh, FILE *fw){
	fseek(fw,0,SEEK_SET);
	unsigned int temp[5];
	temp[0]=fh->magicNumber; fwrite(temp,2,1,fw);
	temp[0]=fh->fileSize; fwrite(temp,4,1,fw);
	temp[0]=fh->reserved; fwrite(temp,2,1,fw);
	temp[0]=fh->reserved2; fwrite(temp,2,1,fw);
	temp[0]=fh->offset; fwrite(temp,4,1,fw);
	return;
}
void setBMPFileDIMHeader(Dimh *fd, FILE *fw){
	fseek(fw,14,SEEK_SET);
	unsigned int temp[10];
	temp[0]=fd->headerSize; fwrite(temp,4,1,fw);
	temp[0]=fd->width; fwrite(temp,4,1,fw);
	temp[0]=fd->height; fwrite(temp,4,1,fw);
	temp[0]=fd->colorPlanes; fwrite(temp,2,1,fw);
	temp[0]=fd->bitPerPixel; fwrite(temp,2,1,fw);
	temp[0]=fd->compressionMethod; fwrite(temp,4,1,fw);
	temp[0]=fd->imageSize; fwrite(temp,4,1,fw);
	temp[0]=fd->horizonalResolution; fwrite(temp,4,1,fw);
	temp[0]=fd->verticalResolution; fwrite(temp,4,1,fw);
	temp[0]=fd->colors; fwrite(temp,4,1,fw);
	temp[0]=fd->importantColors; fwrite(temp,4,1,fw);
	return;
}
void setBMPData(int xsize, int ysize, int nullByte, Pixel *pic, FILE *fw){
	int xcount,ycount,nullcount;
	unsigned int value[2];
	for(xcount=xsize-1;xcount >=0;xcount--){
		for(ycount=0;ycount < ysize;ycount++){
			value[0]=getPixel(pic,xcount,ycount,ysize);
			fwrite(value,3,1,fw);
		}
		value[0]=0x00;
		for(nullcount=0;nullcount<nullByte;nullcount++){
			fwrite(value,1,1,fw);
		}
	}
}
void changeGrayScale(Dimh *fd, Pixel *pic){
	int xcount,ycount,xsize,ysize;
	unsigned int value[3];
	xsize=fd->height;
	ysize=fd->width;
	for(xcount=0;xcount<xsize;xcount++){
		for(ycount=0;ycount<ysize;ycount++){
			value[0]=getGrayscale(pic,xcount,ycount,ysize);
			picP(pic,xcount,ycount,ysize)->r = value[0];
			picP(pic,xcount,ycount,ysize)->g = value[0];
			picP(pic,xcount,ycount,ysize)->b = value[0];
		}	
	}
}
void changeMono(Dimh *fd, Pixel *pic, int threshold){
	int xcount,ycount,xsize,ysize,value;
	xsize=fd->height;
	ysize=fd->width;
	for(xcount=0;xcount<xsize;xcount++){
		for(ycount=0;ycount<ysize;ycount++){
			value=getGrayscale(pic,xcount,ycount,ysize);
			if(value < threshold)
				value=0;
			else
				value=255;
			picP(pic,xcount,ycount,ysize)->r = value;
			picP(pic,xcount,ycount,ysize)->g = value;
			picP(pic,xcount,ycount,ysize)->b = value;
		}	
	}
}
void putAA(Dimh *fd,Pixel *pic,FILE *fw){
	int xcount,ycount,xsize,ysize,value;
	xsize=fd->height;
	ysize=fd->width;
	char t[2];
	for(xcount=0;xcount<xsize;xcount++){
		for(ycount=0;ycount<ysize;ycount++){
			value=getGrayscale(pic,xcount,ycount,ysize);
			value=255-value;
			if(value == 0){
				strncpy(t," ",2);
				//strncpy(t,"一",2);
			}
			else if(value < 5){
				strncpy(t,"一",2);
				//strncpy(t,"十\",2);
			}
			else if(value < 10){
				strncpy(t,"口",2);
			}
			else if(value < 20){
				strncpy(t,"又",2);
			}
			else if(value < 30){
				strncpy(t,"川",2);
			}
			else if(value < 40){
				strncpy(t,"凶",2);
			}
			else if(value < 50){
				strncpy(t,"玉",2);
			}
			else if(value < 60){
				strncpy(t,"池",2);
			}
			else if(value < 70){
				strncpy(t,"赤",2);
			}
			else if(value < 80){
				strncpy(t,"金",2);
			}
			else if(value < 90){
				strncpy(t,"草",2);
			}
			else if(value < 110){
				strncpy(t,"野",2);
			}
			else if(value < 120){
				strncpy(t,"晴",2);
			}
			else if(value < 130){
				strncpy(t,"園",2);
			}
			else if(value < 140){
				strncpy(t,"駅",2);
			}
			else if(value < 150){
				strncpy(t,"輪",2);
			}
			else if(value < 160){
				strncpy(t,"機",2);
			}
			else if(value < 170){
				strncpy(t,"縮",2);
			}
			else if(value < 180){
				strncpy(t,"繭",2);
			}
			else if(value < 190){
				strncpy(t,"臓",2);
			}
			else if(value < 200){
				strncpy(t,"醸",2);
			}
			else if(value < 210){
				strncpy(t,"躍",2);
			}
			else if(value < 220){
				strncpy(t,"襲",2);
			}
			else if(value < 230){
				strncpy(t,"鑑",2);
			}
			else if(value < 255){
				strncpy(t,"■",2);
			}
			putchar(t[0]);
			putchar(t[1]);
		}
		putchar('\n');
	}	
}
int main(int argc,char *argv[]){
	printf("C Language Exercise\n");
	FileReader *fr=NULL;
	FILE *fw=NULL;
	Pixel *pic=NULL;
	BMPFileHeader fh; Dimh fd;
	int xsize,ysize,monoThreshold;
	int nullByte=0 ,startPos=0 ,bpp=0; 
	if((fr=malloc(sizeof(FileReader)))==NULL){
		fprintf(stderr,"Memory allocate error");
		exit(-1);
	}
	printf("FileReader=%dByte\n",(int)sizeof(FileReader));
	if(argc == 1){
		puts("WARN please Load Image FileName");
		exit(-1);
	}
	else if(argc == 2){
		puts("WARN please Write Image FileName");
		exit(-1);
	}
	else if(argc == 3){
		puts("WARN please OutputMode 'gray' or 'mono'");
		exit(-1);
	}
	if((fr->fi=fopen(argv[1],"rb")) == NULL){
		puts("ERROR FileNotFound");
		return 1;
	}
	else{
		printf("%s load Success\n",argv[1]);
	}
	if((fw=fopen(argv[2],"wb")) == NULL){
		puts("ERROR Can't create image file");
		exit(-1);
	}
	else{
		printf("%s Write Success\n",argv[2]);
	}
	unsigned int inbuf[10];
	int i;
	for(i=0;i<3;i++){
		inbuf[i]=0;
	}
	getBMPFileHeader(&fh,fr);
	showBMPFileHeader(&fh);
	getInfomationHeader(fr,&fd);
	xsize=fd.height;
	ysize=fd.width;
	printf("x:%d,y:%d\n",xsize,ysize);

	bpp=(fd.bitPerPixel)/8;	
	startPos=fh.offset;
	int xcount,ycount;
	if((pic=malloc(xsize*ysize*sizeof(Pixel)))==NULL){
		puts("Fail");
		exit(-1);
	}
	else
		printf("Success allocating memory:%d Byte\n",xsize*ysize*sizeof(Pixel));
	if((ysize*bpp)%4 == 0){
		nullByte=0;
	}
	else{
		nullByte=((((ysize * bpp)/4+1)*4) - (ysize * bpp));
	}
	printf("null Byte :%d Byte\n",nullByte);
	for(xcount=xsize-1;xcount >= 0;xcount--){
		for(ycount=ysize-1;ycount >= 0;ycount--){
			setMemoryPixel(pic,getValue(fr,startPos+(xcount * (ysize * bpp + nullByte)) + ycount * bpp,3),xsize-xcount-1,ycount,ysize);

		}
	}
	setBMPFileHeader(&fh,fw);
	setBMPFileDIMHeader(&fd,fw);
	char a1,a2,a3;
	int monocount;
	if(strcmp(argv[3],"gray")==0){
		changeGrayScale(&fd,pic);
	}
	else if(strcmp(argv[3],"mono")==0){
		if(argc == 5){
			for(monocount=0;monocount < strlen(argv[4]);monocount++){
				if(isdigit(argv[4][monocount])==0){
					puts("please input '0 to 255' value");
					fclose(fr->fi); fclose(fw);
					free(fr);
					exit(-1);
				}
				else
					monoThreshold=atoi(argv[4]);
			}	
		}
		changeMono(&fd,pic,monoThreshold);
	}
	else if(strcmp(argv[3],"aa")==0){
		putAA(&fd,pic,fw); 
		fclose(fr->fi); fclose(fw); free(fr);
		return 0;
	}	
	setBMPData(xsize,ysize,nullByte,pic,fw);
	fclose(fr->fi); fclose(fw); free(fr);
	return 0;
}