【輕鬆一刻】Java製作字元動畫

深夜裡的程式猿發表於2019-05-08

前言

今晚閒來無事,整理了一下電腦中塵封已久的舊程式碼,看著那些年自己寫過的程式碼,踩過的坑,頓時老淚縱橫。正當在感嘆之際,突然發現在“馬克思”資料夾下出現了一個好玩的專案,那就是N年前剛學Java時寫的GIF轉字元動畫的小玩具,雖然是個小玩意,但是在當時能搞點東西出來還是非常有成就感的。

正文

效果展示

原圖,某兩年半練習生

【輕鬆一刻】Java製作字元動畫

轉成字元動畫後的練習生

【輕鬆一刻】Java製作字元動畫

實現原理

其實字元動畫的實現原理比較簡單,這裡我們拋開GIF,直接拿一張靜態圖片來說明。
首先我們要把原圖轉成灰度圖,這樣圖片中每個畫素就只存在亮度資訊0-255。

【輕鬆一刻】Java製作字元動畫

取顏色的RGB均值灰度後

【輕鬆一刻】Java製作字元動畫

接著我們可以定義需要使用的字元,每個字元對應一段亮度範圍,比如 圖中的M,@,;等字元,接著我們就可以去遍歷替換圖片中的所有畫素,慢慢的除錯每個字元對應畫素的亮度範圍,除錯到輸出的影像輪轂清晰即可,這樣單張圖片的字元畫就已經成型了。下面關鍵程式碼註釋。

BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
		int width = bi.getWidth();//原圖寬度
		int height = bi.getHeight();//原圖高度
		int minx = bi.getMinX();//BufferedImage 原圖 最小X座標
		int miny = bi.getMinY(); //BufferedImage 原圖 最小Y座標
		for (int i = miny; i < height; i += 8) {//遍歷圖片中的畫素點,用字元判斷畫素範圍來替換
			for (int j = minx; j < width; j += 8) {
				int pixel = bi.getRGB(j, i); // 下面三行程式碼將一個數字轉換為RGB數字
				int red = (pixel & 0xff0000) >> 16;
				int green = (pixel & 0xff00) >> 8;
				int blue = (pixel & 0xff);
				double gray = 0.299 * red + 0.578 * green + 0.114 * blue; //圖片變灰計算公式
				char c = toChar((int) gray); //根據計算出來的gray值返回不同字元
				bufferedWriter.write(c);
			}
			bufferedWriter.newLine();
		}
		//輸出圖片
複製程式碼

若要讀取GIF,輸出GIF,我們可以使用一些開源的包,例如animated-gif,GifDecoder等,通過這些類我們可以讀取到gif的每一幀,然後我們對每一幀的操作都跟上方的靜態圖操作是一致的。處理完每一幀之後再合成GIF輸出即可。(視訊同理)

由於完全自己處理的話,可能會有很多細節需要調整的地方,為了方便,這裡推薦一個專案。Github地址:github.com/korhner/asc… 。使用方法:

// initialize caches
AsciiImgCache smallFontCache = AsciiImgCache.create(new Font("Courier",Font.BOLD, 6));
// initialize ssimStrategy
BestCharacterFitStrategy ssimStrategy = new StructuralSimilarityFitStrategy();

String srcFilePath = "examples/xxx.gif";
String disFilePath = "examples/xxx.gif";
int delay = 100;//ms

GifToAsciiConvert asciiConvert = new GifToAsciiConvert(smallFontCache, ssimStrategy);

asciiConvert.convertGitToAscii(srcFilePath, disFilePath, delay,0);
複製程式碼

只需要簡單的幾行,就可以完成字元動畫的轉換,其原理跟我們上面介紹的基本一致,有興趣的同學可以自行研究。

結語

程式碼除了用來工作,其實還能用在很多能讓我們開心的地方,例如寫點小工具,小遊戲,幫自己或他人解決一些繁瑣的事情,這樣才能在工作多年後任然保持對程式碼的那份初心,不至於被重複的工作磨滅了激情。


公眾號博文同步Github倉庫,有興趣的朋友可以幫忙給個Star哦,碼字不易,感謝支援。

github.com/PeppaLittle…

推薦閱讀

如何優化程式碼中大量的if/else,switch/case?
如何提高使用Java反射的效率?
Java日誌正確使用姿勢
大白話搞懂什麼是同步/非同步/阻塞/非阻塞

有收穫的話,就點個贊吧

關注「深夜裡的程式猿」,分享最乾的乾貨

【輕鬆一刻】Java製作字元動畫

相關文章