Android平臺(tái)下的圖片/視頻轉(zhuǎn)Ascii碼圖片/視頻 (二)

????忙里偷閑又來(lái)寫(xiě)一篇文章,最近在更新一些好玩的圖片算法尾序,當(dāng)然也沒(méi)落下優(yōu)化ascii碼的圖像效果帮掉,這次我將更換一種計(jì)算ascii碼的方式躯概,這樣能更好的添加一些效果,并且更加清楚的講解一下原理即寒。

????在上一篇文章里,有很多人留言給我說(shuō),為什么那個(gè)圖片縮放比為7歹篓,改成6或者5為什么生成的圖片就不正常了瘫证,這一點(diǎn)在我剛開(kāi)始看類似的參考文獻(xiàn)時(shí)也比較費(fèi)解,不過(guò)在我多次的嘗試時(shí)滋捶,發(fā)現(xiàn)7這個(gè)比例是最好的痛悯,至于原因,我講出來(lái)想必你們肯定會(huì)失望了重窟,因?yàn)槲蚁胝f(shuō)的是12號(hào)字符#8XOHLTI)i=+;:,.這幾個(gè)在staticlayout里繪制出來(lái)以后大概占用7像素载萌,想想,一個(gè)像素替換成了一個(gè)ascii碼,如果圖片縮放為屏幕寬的1/7巡扇,替換成字符以后扭仁,又會(huì)變成正好占滿屏幕寬的ascii碼圖片。所以當(dāng)改成縮放比為6厅翔,或者5以下時(shí)乖坠,由于一行像素替換成字符時(shí),staticlayout再生成屏幕寬的圖片時(shí)刀闷,因?yàn)橐粋€(gè)字符占用7像素熊泵,所以在未到達(dá)換行符\n時(shí)會(huì)提前換行,導(dǎo)致生成的圖片不正確甸昏。

????因?yàn)槲乙膊幌矚g猜或者試出來(lái)的方式來(lái)搞效果顽分,因此我又想出了另一種方法生成ascii碼圖片,我選取了筆畫(huà)具有代表性的漢字:"一七刀九上工土開(kāi)天月”,當(dāng)然我方法預(yù)留了可以使用其他字的地方施蜜,然后我對(duì)這些字進(jìn)行以下處理:

  • 首先用Canvas繪制出這些字 使用Paint.FontMetrics fontMetrics = paint.getFontMetrics();測(cè)量出字繪制出來(lái)以后黑色的像素塊float distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;這個(gè)distance變量為繪制中心距離繪制baseline的距離卒蘸,(這個(gè)地方不懂的具體可以百度android drawtext)
final String base = "一七刀九上工土開(kāi)天月";// 隨機(jī)字符串  當(dāng)然如果你想更改成別的字符串也行,不過(guò)字符串的每個(gè)字最好涵蓋各個(gè)復(fù)雜程度的字符
//            final String base = "#8XOHLTI)i=+; :,.";// 隨機(jī)字符串
            float maxCharWidth = 0;
            Map<Character, Integer> blackMap = new HashMap<>();
//        final String base = "#8XOHLTI)i=+;:,.";// 隨機(jī)字符串
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(Color.BLACK);
            paint.setStrokeWidth(0.1f);
            paint.setTextAlign(Paint.Align.CENTER);
            paint.setTextSize(10);
            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
            float distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
            for (int i = 0; i < base.length(); i++) {
                float width = paint.measureText(base.charAt(i) + "");
                Bitmap bitmap = Bitmap.createBitmap(((int) width), ((int) (fontMetrics.bottom - fontMetrics.top)), Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);
                canvas.drawColor(Color.WHITE);
                canvas.drawText(base.charAt(i) + "", 0, 1, bitmap.getWidth() / 2, bitmap.getHeight() / 2 + distance, paint);
                int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
                bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
                int gray = 0;
                for (int pixel : pixels) {
                    if (pixel != -1) {
                        gray++;
                    }
                }
                blackMap.put(base.charAt(i), gray);
                int charWidth = bitmap.getWidth();
                int charHeight = bitmap.getHeight();
                if (maxCharWidth < Math.max(charWidth, charHeight)) {
                    maxCharWidth = Math.max(charWidth, charHeight);
                }
                bitmap.recycle();
            }
//            maxCharWidth *= (5 / 6f);
            Character[] characters = new Character[base.length()];
            for (int i = 0; i < characters.length; i++) {
                characters[i] = base.charAt(i);
            }
            Arrays.sort(characters, new Comparator<Character>() {
                @Override
                public int compare(Character o1, Character o2) {
                    return blackMap.get(o2) - blackMap.get(o1);
                }
            });

這里就是遍歷每一個(gè)字符翻默,繪制出來(lái)以后缸沃,保存所有字符最大的寬高,以此來(lái)像活字印刷一樣修械,一個(gè)字符作為一個(gè)替換的像素群塊,比如我以10字號(hào)大小來(lái)繪制每一個(gè)字符趾牧,對(duì)每一個(gè)漢字繪制出來(lái)以后需要用到多少個(gè)像素點(diǎn)(用像素點(diǎn)的多少來(lái)代表漢字的復(fù)雜程度),遍歷計(jì)算完肯污,發(fā)現(xiàn)最大寬高為8像素,然后我對(duì)base String進(jìn)行排序武氓,漢字復(fù)雜程度降序排列,如果過(guò)于亮的地方就用筆畫(huà)少的字替換沒(méi)毛病吧仇箱?

  • 緊接著對(duì)原圖像進(jìn)行縮放县恕,使他的寬為屏幕寬,這樣生成的圖片不會(huì)過(guò)大剂桥,也不會(huì)過(guò)小導(dǎo)致效果不好看忠烛。
    (這里就不貼縮放代碼了,想必各位android老鐵縮放圖片比我熟練)
  • 緊接著就到了重頭戲了权逗,剛才我第一步算出來(lái)了每一個(gè)待替換字符繪制出來(lái)的最大寬高,然后就以這個(gè)寬高一個(gè)塊一個(gè)塊像國(guó)際象棋格子一樣的美尸,替換掉同樣大小的原圖像素塊冤议,這里bitmap只能重新創(chuàng)建一個(gè),因?yàn)槭莇ecode的bitmap师坎,原來(lái)的像素?cái)?shù)組不可修改恕酸。然后兩層for循環(huán)遍歷每一個(gè)分割的小塊,計(jì)算出原圖像這個(gè)小塊左上角的像素點(diǎn)的灰度值胯陋,計(jì)算出這個(gè)灰度值在0到255內(nèi)的哪個(gè)地方蕊温,因?yàn)槿绻麕鎿Q的字符為9個(gè),那么就要分割成10份遏乔,要給空字符做為替換過(guò)于明亮的地方义矛。(這里我就不求每一個(gè)原圖像小塊,比如10x10盟萨,內(nèi)所有的像素點(diǎn)的灰度值了凉翻,java的效率你懂得,其實(shí)用一個(gè)像素來(lái)代表這個(gè)小像素塊足夠了),比如這個(gè)像素的灰度值為10捻激,在0到255里制轰,屬于10個(gè)部分中的第一部分,是比較暗的部分胞谭,那么我就用10個(gè)可替換漢字中筆畫(huà)最多的漢字來(lái)替換(當(dāng)然在最開(kāi)始提供可替換字符時(shí)垃杖,最好不要提供筆畫(huà)過(guò)于多的漢字,因?yàn)檫@樣會(huì)導(dǎo)致生成的圖片過(guò)于胡一片)韭赘。
for (int y = 0; y < image.getHeight(); y += maxCharWidth) {
                for (int x = 0; x < image.getWidth(); x += maxCharWidth) {
//                    Log.i("icv", "繪制x=" + (x + 6f) + " y=" + (y + 6));
                    final int pixel = image.getPixel(x, y);
                    final int r = (pixel & 0xff0000) >> 16, g = (pixel & 0xff00) >> 8, b = pixel & 0xff;
                    final int gray = (int) (0.299f * r + 0.578f * g + 0.114f * b);
                    final int index = Math.round(gray * (characters.length + 1) / 255);
                    paint.setColor(Color.rgb(gray, gray, gray));
                    outCanvas.drawText(index >= characters.length ? " " : String.valueOf(characters[index]), x + maxCharWidth / 2f, y + maxCharWidth / 2f + distance, paint);
                }
            }
  • 還有一個(gè)神來(lái)之筆的步驟:如果你想生成彩色的字符,那么就把原圖像蓋在下面势就,讓目前生成的字符畫(huà)作為模板泉瞻,讓下面的顏色投過(guò)來(lái),話不多說(shuō)苞冯,上代碼:
          if (isColorful) {
                for (int y = 0; y < outImage.getHeight(); y++) {
                    for (int x = 0; x < outImage.getWidth(); x++) {
                        if (outImage.getPixel(x, y) != Color.WHITE) {
                            outImage.setPixel(x, y, image.getPixel(x, y));
                        }
                    }
                }
            }
            image.recycle();

最后放一個(gè)效果圖吧:


大公主黑白.png

大公主彩色.png

抖音

系列文章:
Android平臺(tái)下的圖片/視頻轉(zhuǎn)Ascii碼圖片/視頻 (一)
Android平臺(tái)下的圖片/視頻轉(zhuǎn)Ascii碼圖片/視頻 (二)

參考文獻(xiàn):
無(wú)參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末袖牙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子舅锄,更是在濱河造成了極大的恐慌鞭达,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件皇忿,死亡現(xiàn)場(chǎng)離奇詭異畴蹭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)鳍烁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)叨襟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人幔荒,你說(shuō)我怎么就攤上這事糊闽∈崦担” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵右犹,是天一觀的道長(zhǎng)提澎。 經(jīng)常有香客問(wèn)我,道長(zhǎng)念链,這世上最難降的妖魔是什么盼忌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮钓账,結(jié)果婚禮上碴犬,老公的妹妹穿的比我還像新娘。我一直安慰自己梆暮,他們只是感情好服协,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著啦粹,像睡著了一般偿荷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上唠椭,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天跳纳,我揣著相機(jī)與錄音,去河邊找鬼贪嫂。 笑死寺庄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的力崇。 我是一名探鬼主播斗塘,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼亮靴!你這毒婦竟也來(lái)了馍盟?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤茧吊,失蹤者是張志新(化名)和其女友劉穎贞岭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體搓侄,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞄桨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了讶踪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片讲婚。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俊柔,靈堂內(nèi)的尸體忽然破棺而出筹麸,到底是詐尸還是另有隱情活合,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布物赶,位于F島的核電站白指,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏酵紫。R本人自食惡果不足惜告嘲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奖地。 院中可真熱鬧橄唬,春花似錦、人聲如沸参歹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)犬庇。三九已至僧界,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間臭挽,已是汗流浹背捂襟。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留欢峰,地道東北人葬荷。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像纽帖,于是被迫代替她去往敵國(guó)和親宠漩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348