Android做到圖片轉ascii打字符圖的一些嘗試

工程師大咖

點擊右側關注,免費進階高級!

這是手機端的

還有一個普通的頭像,做成ascii圖後,簡直美到窒息

下面開始分析代碼,首先根據圖片像素灰度轉為ascii字符,這在網上有現成的java代碼,android上只需要改一點api就可以,代碼如下。

publicstaticBitmapcreateAsciiPic(finalStringpath,Contextcontext){finalStringbase="#8XOHLTI)i=+;:,.";//字符串由複雜到簡單//finalStringbase="#,.0123456789:;@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";//字符串由複雜到簡單StringBuildertext=newStringBuilder();WindowManagerwm=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);DisplayMetricsdm=newDisplayMetrics();wm.getDefaultDisplay().getMetrics(dm);intwidth=dm.widthPixels;intheight=dm.heightPixels;Bitmapimage=BitmapFactory.decodeFile(path);//讀取圖片intwidth0=image.getWidth();intheight0=image.getHeight();intwidth1,height1;intscale=7;if(width0<=width/scale){width1=width0;height1=height0;}else{width1=width/scale;height1=width1*height0/width0;}image=scale(path,width1,height1);//讀取圖片//輸出到指定文件中for(inty=0;y<image.getHeight();y+=2){for(intx=0;x<image.getWidth();x++){finalintpixel=image.getPixel(x,y);finalintr=(pixel&0xff0000)>>16,g=(pixel&0xff00)>>8,b=pixel&0xff;finalfloatgray=0.299f*r+0.578f*g+0.114f*b;finalintindex=Math.round(gray*(base.length()+1)/255);Strings=index>=base.length()?"":String.valueOf(base.charAt(index));text.append(s);}text.append("");}returntextAsBitmap(text,context);}

這樣處理完得到的ascii文本,但我們需要的是ascii圖片,那我們需要怎麼做呢,截屏?

請讀者思考10秒鐘,想想自己的解決方案。

我這里通過TextPanit和StaticLayout做到的,也可以new一個TextView,寫入文本,然後把Textview的緩沖區轉換為圖片,但是這種StaticLayout的方式更底層,更有效,代碼如下:

publicstaticBitmaptextAsBitmap(StringBuildertext,Contextcontext){TextPainttextPaint=newTextPaint();textPaint.setColor(Color.BLACK);textPaint.setAntiAlias(true);textPaint.setTypeface(Typeface.MONOSPACE);textPaint.setTextSize(12);WindowManagerwm=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);DisplayMetricsdm=newDisplayMetrics();wm.getDefaultDisplay().getMetrics(dm);intwidth=dm.widthPixels;StaticLayoutlayout=newStaticLayout(text,textPaint,width,Layout.Alignment.ALIGN_CENTER,1f,0.0f,true);Bitmapbitmap=Bitmap.createBitmap(layout.getWidth()+20,layout.getHeight()+20,Bitmap.Config.ARGB_8888);Canvascanvas=newCanvas(bitmap);canvas.translate(10,10);canvas.drawColor(Color.WHITE);layout.draw(canvas);Log.d("textAsBitmap",String.format("1:%d%d",layout.getWidth(),layout.getHeight()));returnbitmap;}

相對於電腦端有無邊無際的txt編輯框,android里text是有字數限制的,所以原始圖片如果像素過多的話就要進行尺寸壓縮。

而且textPaint的這個設置特別重要textPaint.setTypeface(Typeface.MONOSPACE);字體對效果的影響太大了,失之毫厘謬以千里,這是一個大坑,說多了都是時間。

我在項目里集成了一個圖片選擇庫,可以直接把拍的照片轉化為ascii圖,碰到一個問題就是拍照圖片拿到後都會自動旋轉90度,很是困惑,雖然找到了處理方法,但系統為什麼要作旋轉處理,還請知道的大神告知原因。

處理代碼如下:

publicstaticStringamendRotatePhoto(Stringoriginpath,Contextcontext){//取得圖片旋轉角度intangle=readPictureDegree(originpath);//把原圖壓縮後得到Bitmap對象if(angle!=0){Bitmapbmp=getCompressPhoto(originpath);Bitmapbitmap=rotaingImageView(angle,bmp);returnsavePhotoToSD(bitmap,context);}else{returnoriginpath;}}

用到的方法:

publicstaticintreadPictureDegree(Stringpath){intdegree=0;try{ExifInterfaceexifInterface=newExifInterface(path);intorientation=exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL);switch(orientation){caseExifInterface.ORIENTATION_ROTATE_90:degree=90;break;caseExifInterface.ORIENTATION_ROTATE_180:degree=180;break;caseExifInterface.ORIENTATION_ROTATE_270:degree=270;break;}}catch(IOExceptione){e.printStackTrace();}returndegree;}publicstaticBitmaprotaingImageView(intangle,Bitmapbitmap){BitmapreturnBm=null;//根據旋轉角度,生成旋轉矩陣Matrixmatrix=newMatrix();matrix.postRotate(angle);try{//將原始圖片按照旋轉矩陣進行旋轉,並得到新的圖片returnBm=Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);}catch(OutOfMemoryErrore){}if(returnBm==null){returnBm=bitmap;}if(bitmap!=returnBm){bitmap.recycle();}returnreturnBm;}

這些代碼都在文末的項目里。

按說拿到ascii圖後,想要把整個視頻轉換成ascii字符視頻就很簡單了。只要把視頻逐幀抽成圖片,圖片轉換後,再合成為視頻播放出來,但我視頻庫用的不多,希望有能力的朋友可以幫助完成最後一步。

最後,也希望朋友們能把一些有趣的想法實踐到android項目中來,讓搬磚之餘,有更多的樂趣。

github地址

https://github.com/meiniepan/Pic2Ascii

Android做到圖片轉ascii打字符圖的一些嘗試

【點擊成為源碼大神】