画像からアスキーアート作成
超適当なソース.汚すぎるけれど,バックアップとして置いておく.
しばらく全く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; }