用Java生成字符畫

ASCII碼藝術是一種技術,它利用ASCII標準中的可打印字符來產生視覺藝術效果。在歷史上它有其存在的目的,當時的打印機還無法打印圖片,並且當時在郵件中嵌入圖像還無法實現,所以它也用於郵件中。本文中,我將爲你呈現一個非常簡單的ASCII碼藝術產生器,它由Java語言編寫,並可以配置字體和對比度。因爲該產生器是我在週末用幾個小時創建的,所以它還不完美,但卻是一個有趣的實驗。在下面你可以看到實現代碼,並且我將解釋它的工作原理。

算法

這個算法很簡單。首先,我們將ASCII碼藝術品中要用到的每一個字符轉化成一張圖片,並緩存它。然後,我們遍歷原始圖像,對於每個字符大小的圖片塊,找出能最佳匹配它的字符。爲了實現這一步,我們首先對原始圖像做一些預處理:我們先將圖像轉換爲灰度圖,然後讓其通過一個閾值濾波器,此時就得到了一個黑白對比圖,我們可以將其與每個字符對比並計算差值。接着,對每個圖片塊選取最相似的字符,一直進行下去,直到整個圖像都轉換完成。此外,我們還可以根據需要調 整閾值大小來影響對比度,並增強最終的結果。

爲了實現這一點,一個非常簡單的方法是將紅、綠、藍的值都設置成三種顏色的平均值:

=綠=藍 =(紅+綠+藍)/ 3

如果這個值低於閾值,我們就將它設置成白色,否則我們將其設置成黑色。最後,我們將圖像與每個字符以像素爲單位進行比較並計算出平均誤差。如下面的圖片和代碼片段所示:

int r1 = (charPixel >> 16) & 0xFF;
int g1 = (charPixel >> 8) & 0xFF;
int b1 = charPixel & 0xFF;

int r2 = (sourcePixel >> 16) & 0xFF;
int g2 = (sourcePixel >> 8) & 0xFF;
int b2 = sourcePixel & 0xFF;

int thresholded = (r2 + g2 + b2) / 3 < THRESHOLD ? 0 : 255;

error = Math.sqrt((r1 - thresholded) * (r1 - thresholded) + 
    (g1 - thresholded) * (g1 - thresholded) + (b1 - thresholded) * (b1 - thresholded));

因爲顏色是存儲在單個整數中,所以我們首先提取單個顏色成分並執行上面我解釋的計算。另一個挑戰是準確地測量字符尺寸,並以它們爲中心作圖。在試驗了多種方法之後,我最終發現這個方法已經足夠好:

Rectangle rect = new TextLayout(Character.toString((char) i), fm.getFont(), 
    fm.getFontRenderContext()).getOutline(null).getBounds();

g.drawString(character, 0, (int) (rect.getHeight() - rect.getMaxY()));
發佈了1 篇原創文章 · 獲贊 4 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章