你还记得"老"的互联网吗?在网络浏览器出现之前,当一切都有强烈的Unix味道的时候?当时有一种叫做ASCII艺术的东西,也就是用ASCII字母来创造一个图像。下面是一个获取图像(640x384)并将其转换为ASCII字符串的程序。我想为一个
T—恤衫
您需要将字体目录中的"Courier new"字体复制到与脚本相同的目录中,并添加一个需要转换的图像:
- import Image, ImageDraw
- import ImageFont
- import math
-
- # funny useless program
-
- lu = []
- for i in range(125-32):
- lu.append(chr(i+33))
- i2 = Image.new("RGBA",(64,64))
- ii = Image.open("mona.png") # change this to your own picture, but it needs to be 640x384!
- im = Image.new("RGBA",(64,64))
- d = ImageDraw.Draw(im)
- f = ImageFont.truetype("courbi.ttf",13)
-
- str=""
- for v in range(24):
- print v
- for k in range(80):
- chr = ""
- maxdiff = 0xffffff
- for e in lu:
- d.rectangle([0,0,64,64], fill=0)
- d.text((0,0),e,font=f,fill=0xffffff)
- diff = 0
- r0 = 0
- g0 = 0
- b0 = 0
- for a in range(16):
- for b in range(8):
- c = im.getpixel((b,a))[0]
- c0 = (ii.getpixel((b+(k*8),a+(v*16)))[0] + ii.getpixel((b+(k*8),a+(v*16)))[1] + ii.getpixel((b+(k*8),a+(v*16)))[2])/3.0
- r0+= ii.getpixel((b+(k*8),a+(v*16)))[0]
- g0+= ii.getpixel((b+(k*8),a+(v*16)))[1]
- b0+= ii.getpixel((b+(k*8),a+(v*16)))[2]
-
- diff+=abs(c-c0)
- if(diff < maxdiff):
- maxdiff = diff
- chr = e
-
- r0*=1.0
- g0*=1.0
- b0*=1.0
- r0/=(16.0*8.0)
- g0/=(16.0*8.0)
- b0/=(16.0*8.0)
- ir0 = int(r0)
- ig0 = int(g0)
- ib0 = int(b0)
-
- r1 = hex(ir0)
- r1 = r1[2:len(r1)]
- g1 = hex(ig0)
- g1 = g1[2:len(g1)]
- b1 = hex(ib0)
- b1 = b1[2:len(g1)]
-
- if(chr == " "):
- chr=" "
-
- str+="<td width=\"8px\"><font size=\"1px\" color=\"#"+r1+g1+b1+"\">"+chr+"</font></td>"
- str="<tr>"+str+"</tr>"
-
- str= "<html><body bgcolor=\"#000000\"><table width=\"640px\" height=\"386px\">"+str+"</table></body></html>"
- f = open("mona.txt","w")
- f.write(str)
- f.close()
-
该程序将其输出为.html文件,但它应该很容易修改,因此它将输出txt。
-赞誉
# 回答1
我已经修改了您的代码,做了一些不同的事情。
它极大地加快了速度。我把6分钟缩短到了1秒。我还让它在命令行解析器的基础上运行,所以你现在可以把它放在你的网站上或任何你想要的地方。如果我没记错的话,这里面有几个问题(我写这篇文章大约有6个月了)。请随意调整它,并将其带回给每个人。它还在算法中使用真实亮度(如果需要)。
- '''
- Inspired by -Kudos code from http://bytes.com/topic/python/insights/874180-ascii-art-creator
- Pretty much a rewrite, but I give kudos complete props for posting this and making it fun and easy
- '''
-
-
- import sys,os
- import Image, ImageDraw
- import ImageFont
- import math
- import time, random
- from optparse import OptionParser
-
-
- # funny useless program
- t0 = time.time();
- VERBOSE_LEVEL = 1;
- MIN_LUM_DEFAULT = .1;
- MAX_LUM_DEFAULT = 1.0;
- OFFSET_LUM_DEFAULT = 0;
- OUTPUT_FONT_SIZE_DEFAULT = 3;
- CHARMAP_DEFAULT = 'luminance';
-
- ROWS_DEFAULT = 24
- COLS_DEFAULT = 80
-
- MAX_RGB = 255
- MAX_F_RGB = float(MAX_RGB)
-
- def normalizePixel( rgb ):
- return rgb[0]/MAX_F_RGB,rgb[1]/MAX_F_RGB,rgb[2]/MAX_F_RGB
-
- def getLuminancePixel( rgb ):
- nR,nG,nB = normalizePixel( rgb )
- return nR*0.299 + nG*0.587 + nB*0.114
-
- def output( val, vLevel=0 ):
- if vLevel <= VERBOSE_LEVEL:
- print ( val )
-
- def main( args ):
-
- global VERBOSE_LEVEL;
-
- parser = OptionParser()
- parser.add_option("-f", "--file", action='append', dest="files", help="process these files", metavar="LIST")
- parser.add_option( "--characters", action="store", dest="characters", help="characters to use")
- parser.add_option( "--character_map", action="store", dest="characterMap", help="maps characters: luminance, order, random")
- parser.add_option("-r", "--rows", action="store", dest="rows", help="number of rows")
- parser.add_option("-c", "--columns", action="store", dest="columns", help="number of columns")
- parser.add_option( "--min_luminance", action="store", dest="minLuminance", help="min luminance value to clip at black")
- parser.add_option( "--max_luminance", action="store", dest="maxLuminance", help="max luminance value to clip at white")
- parser.add_option( "--offset_luminance", action="store", dest="offsetLuminance", help="offset luminance value")
- parser.add_option( "--output_font_size", action="store", dest="outputFontSize", help="output font size in px")
- parser.add_option('-v', "--verbose", action="store", dest="verbose", help="verbosity: 0=None, 1=completion output, 2=image info, 3=pixel blending info")
-
- (options, args) = parser.parse_args( args )
-
- files = options.files;
- characters = options.characters;
- characterMap = options.characterMap;
- rows = options.rows;
- columns = options.columns;
- minLum = options.minLuminance;
- maxLum = options.maxLuminance;
- offsetLum = options.offsetLuminance;
- outputFontSize = options.outputFontSize;
- verbose = options.verbose;
-
- errors = [];
- # SANITY CHECKS
-
- if verbose:
- try:
- VERBOSE_LEVEL = int(verbose);
- except:
- VERBOSE_LEVEL = VERBOSE_LEVEL;
-
- if not files:
- errors.append('Failed to get files: make sure you specify files to use');
- if not characters:
- characters = []
- for i in range( 125-32):
- characters.append( chr( i + 33) );
- else:
- characters = str(characters);
-
- if characterMap:
- if characterMap.lower() in ('luminance','order','random'):
- characterMap = characterMap.lower();
- else:
- characterMap = CHARMAP_DEFAULT;
- else:
- characterMap = CHARMAP_DEFAULT;
-
- try:
- rows = int(rows);
- except:
- rows = ROWS_DEFAULT;
- try:
- columns = int(columns);
- except:
- columns = COLS_DEFAULT;
-
- try:
- minLum = float( minLum)
- except:
- minLum = MIN_LUM_DEFAULT
- try:
- maxLum = float( maxLum)
- except:
- maxLum = MAX_LUM_DEFAULT
-
- try:
- offsetLum = int( offsetLum)
- except:
- offsetLum = OFFSET_LUM_DEFAULT
-
- try:
- outputFontSize = int( outputFontSize)
- except:
- outputFontSize = OUTPUT_FONT_SIZE_DEFAULT
-
- if errors:
- for err in errors:
- output( 'ERROR: %s'%err, 0);
- return -1;
-
- output( 'verbose: %s'%verbose , 3 );
- output( 'files: %s'%files , 3 );
- output( 'characters: %s'%characters , 3 );
- output( 'character_map: %s'%characterMap , 3 );
- output( 'rows: %s'%rows , 3 );
- output( 'columns: %s'%columns , 3 );
- output( 'minLum: %s'%minLum , 3 );
- output( 'maxLum: %s'%maxLum , 3 );
- output( 'offsetLum: %s'%offsetLum , 3 );
- output( 'outputFontSize: %s'%outputFontSize , 3 );
-
- imgChr = Image.new("RGBA",(64,64))
- drwObj = ImageDraw.Draw(imgChr)
- fntObj = ImageFont.truetype("courbi.ttf",13)
-
-
- # build the value table
- lumLUT_Tmp = list();
- lumLUT = list();
- lumToCharTmp = dict();
- maxLum = 0.0;
- minLum = 1.0;
- for ch in characters:
-
- w,h = fntObj.getsize(ch)
- drwObj.rectangle([0,0,64,64], fill=0)
- drwObj.text((0,0),ch,font=fntObj,fill=0xffffff)
- diff = 0
- r0 = 0
- g0 = 0
- b0 = 0
-
- lum = 0;
- for a in range(16):
- for b in range(8):
- lum += getLuminancePixel( imgChr.getpixel((b,a)) )
- lum = lum/(16*8)
- lumLUT_Tmp.append( lum )
- lumToCharTmp[lum] = ch ;
-
- if lum > maxLum:
- maxLum = lum;
- if lum < minLum:
- minLum = lum;
-
- output( ('ch: %s\t(%sx%s) lum:%s'%(ch,w,h,lum)), 3);
- lumToChar = dict();
- for lum in lumLUT_Tmp:
- nLum = (lum-minLum)/(maxLum-minLum);
- lumToChar[nLum] = lumToCharTmp[lum];
- lumLUT.append( nLum );
-
- lumLUT.sort();
-
- for file in files:
- tImage = time.time()
- imgSrc = Image.open(file)
- iw,ih = imgSrc.size;
- cellW = iw/columns;
- cellH = ih/rows;
- #~ print '\n%sx%s %sx%s'%(cellW,cellH, iw, ih)
- sVal=""
- index=0
- for x in range(rows):
- for y in range(columns):
- ch = ""
- maxdiff = 0xffffff
-
- iLum = 0;
- r = 0;
- g = 0;
- b = 0;
- for xCell in range(cellH):
- for yCell in range(cellW):
- color = imgSrc.getpixel((yCell+(y*cellW),xCell+(x*cellH)));
- r += color[0]
- g += color[1]
- b += color[2]
-
- # average
- r = r/(cellH*cellW*1.0);
- g = g/(cellH*cellW*1.0);
- b = b/(cellH*cellW*1.0);
-
- hexColor = '%.2x%.2x%.2x'%( r+offsetLum,g+offsetLum,b+offsetLum );
-
- # normalize
- iLum += getLuminancePixel( (r,g,b) )
-
- #~ r /= MAX_F_RGB;
- #~ g /= MAX_F_RGB;
- #~ b /= MAX_F_RGB;
-
- if characterMap == 'luminance' :
- ix = 0;
- for lum in lumLUT:
- if iLum < MIN_LUM_DEFAULT:
- ch = ' ';
- break;
- if iLum > MAX_LUM_DEFAULT:
- ch = lumToChar[lumLUT[-1]];
- break;
- if lum > iLum:
- try:
- ch = lumToChar[lumLUT[ix]];
- except:
- ch = lumToChar[lumLUT[0]]
- break;
- ix+=1;
-
- elif characterMap == 'order':
- if index >= len(characters):
- index=0;
- ch = characters[index];
- elif characterMap == 'random':
- ch = characters[int(random.random()*len(characters))];
-
- index+=1
- if(ch == " "):
- ch=" "
- #~ output( 'Character: %s'%ch, 3);
- output( ('character: %s\trow:%s column:%s\tlum: %s\tr:%s g:%s b:%s\thex_color:%s'%(ch,x,y,iLum,r,g,b,hexColor)), 3);
- sVal += '''<font size="%spx" color="#%s">%s</font></td>'''%(outputFontSize,hexColor,ch);
- sVal += '<br/>';
- sVal= "<html><body bgcolor=\"#000000\"><pre>"+sVal+"</pre><br/>\n<img src=\"%s\"/>\n</body></html>"%file
- try:
- f = open("%s.html"%file,"w")
- f.write(sVal)
- f.close()
- except:
- output('Failed to write file: %s'%file, 0 );
-
- output( ('%s (%sx%s : %sx%s)'%(file,iw,ih,cellW,cellH)).center(50,'.'), 2)
- output( 'IMAGE PROCESS TIME: %s (sec)\t%s'%((time.time()-tImage),os.path.basename(file)), 1);
-
- output( '%s\nTOTAL PROCESS TIME: %s (sec)'%('-'*100, (time.time()-t0) ), 1);
-
- if __name__=='__main__':
- args = sys.argv;
-
- args += [
- #~ '--file','./angry_birds.jpg',
- #~ '--characters','-+=@!?%$#^&*()[]{}_\\/><,.`~',
- #~ '-r','80', '-c','260',
- #~ '--output_font_size','1',
- #~ '--character_map','random',
- #~ '--character_map','order',
- #~ '-v', '3',
-
- ]
-
- sys.exit( main( args ) );
-
-