極樂凈土----Android實現(xiàn)圖片轉ascii碼字符圖的一些嘗試

抖音上炫代碼的不少嘹屯,有些真的讓人嘆為觀止,作為一個androider从撼,當我看到下面這段舞蹈的時候州弟,終于忍不住了,想要通過android實現(xiàn)一樣的效果低零。


jilejingtu.gif

這么好玩的東西婆翔,為啥就沒有大佬做呢,原因可能有兩個掏婶,一是真的難啃奴,二是出力不討好,難以達到最終效果气堕,一番嘗試后纺腊,技術問題都解決了畔咧,但并沒有達到電腦端美感,手機屏幕還是太小了揖膜。誓沸。
這是電腦端的靜態(tài)圖


ASCII-微信圖片_20180821140237.gif

這是手機端的
微信圖片_20180830113218.jpg

猜猜下面這張是誰


ddd.png

下面開始分析代碼,首先根據(jù)圖片像素灰度轉為ascii字符壹粟,這在網上有現(xiàn)成的java代碼拜隧,android上只需要改一點api就可以,代碼如下

public static Bitmap createAsciiPic(final String path, Context context) {
        final String base = "#8XOHLTI)i=+;:,.";// 字符串由復雜到簡單
//        final String base = "#,.0123456789:;@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";// 字符串由復雜到簡單
        StringBuilder text = new StringBuilder();
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        int width = dm.widthPixels;
        int height = dm.heightPixels;
        Bitmap image = BitmapFactory.decodeFile(path);  //讀取圖片
        int width0 = image.getWidth();
        int height0 = image.getHeight();
        int width1, height1;
        int scale = 7;
        if (width0 <= width / scale) {
            width1 = width0;
            height1 = height0;
        } else {
            width1 = width / scale;
            height1 = width1 * height0 / width0;
        }
        image = scale(path, width1, height1);  //讀取圖片
        //輸出到指定文件中
        for (int y = 0; y < image.getHeight(); y += 2) {
            for (int x = 0; x < image.getWidth(); x++) {
                final int pixel = image.getPixel(x, y);
                final int r = (pixel & 0xff0000) >> 16, g = (pixel & 0xff00) >> 8, b = pixel & 0xff;
                final float gray = 0.299f * r + 0.578f * g + 0.114f * b;
                final int index = Math.round(gray * (base.length() + 1) / 255);
                String s = index >= base.length() ? " " : String.valueOf(base.charAt(index));
                text.append(s);
            }
            text.append("\n");
        }
        return textAsBitmap(text, context);
//        return image;
    }

這樣處理完得到的ascii文本趁仙,但我們需要的是ascii圖片洪添,那我們需要怎么做呢,截屏雀费?請讀者思考10秒鐘干奢,想想自己的解決方案。我這里通過TextPanit和staticLayout實現(xiàn)的盏袄,也可以new一個TextView忿峻,寫入文本,然后把Textview的緩沖區(qū)轉換為圖片辕羽,但是這種staticLayout的方式更底層逛尚,更有效,代碼如下

public static Bitmap textAsBitmap(StringBuilder text, Context context) {

        TextPaint textPaint = new TextPaint();

// textPaint.setARGB(0x31, 0x31, 0x31, 0);

        textPaint.setColor(Color.BLACK);

        textPaint.setAntiAlias(true);
        textPaint.setTypeface(Typeface.MONOSPACE);

        textPaint.setTextSize(12);
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(dm);
        int width = dm.widthPixels;         //

        StaticLayout layout = new StaticLayout(text, textPaint, width,

                Layout.Alignment.ALIGN_CENTER, 1f, 0.0f, true);

        Bitmap bitmap = Bitmap.createBitmap(layout.getWidth() + 20,

                layout.getHeight() + 20, Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmap);

        canvas.translate(10, 10);

        canvas.drawColor(Color.WHITE);

//        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//繪制透明色

        layout.draw(canvas);

        Log.d("textAsBitmap",

                String.format("1:%d %d", layout.getWidth(), layout.getHeight()));

        return bitmap;

    }

相對于電腦端有無邊無際的txt編輯框刁愿,android里text是有字數(shù)限制的绰寞,所以原始圖片如果像素過多的話就要進行尺寸壓縮。而且textPaint的這個設置特別重要textPaint.setTypeface(Typeface.MONOSPACE);字體對效果的影響太大了铣口,失之毫厘謬以千里滤钱,這是一個大坑,說多了都是時間枷踏。
我在項目里集成了一個圖片選擇庫菩暗,可以直接把拍的照片轉化為ascii圖,碰到一個問題就是拍照圖片拿到后都會自動旋轉90度旭蠕,很是困惑,雖然找到了處理方法旷坦,但系統(tǒng)為啥要作旋轉處理掏熬,還請知道的大神告知原因。處理代碼如下

/**
     * 讀取照片旋轉角度
     *
     * @param path 照片路徑
     * @return 角度
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }
public static String amendRotatePhoto(String originpath, Context context) {

        // 取得圖片旋轉角度
        int angle = readPictureDegree(originpath);

        // 把原圖壓縮后得到Bitmap對象
        if (angle != 0) {
            Bitmap bmp = getCompressPhoto(originpath);
            Bitmap bitmap = rotaingImageView(angle, bmp);
            return savePhotoToSD(bitmap, context);
        } else {
            return originpath;
        }

    }
public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
        Bitmap returnBm = null;
        // 根據(jù)旋轉角度秒梅,生成旋轉矩陣
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        try {
            // 將原始圖片按照旋轉矩陣進行旋轉旗芬,并得到新的圖片
            returnBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        } catch (OutOfMemoryError e) {
        }
        if (returnBm == null) {
            returnBm = bitmap;
        }
        if (bitmap != returnBm) {
            bitmap.recycle();
        }
        return returnBm;
    }

這些代碼都在文末的項目里。
按說拿到ascii圖后捆蜀,想要把整個視頻轉換成ascii字符視頻就很簡單了疮丛。只要把視頻逐幀抽成圖片幔嫂,圖片轉換后,再合成為視頻播放出來誊薄,但我視頻庫用的不多履恩,希望有能力的朋友可以幫助完成最后一步。
最后呢蔫,也希望朋友們能把一些有趣的想法實踐到android項目中來切心,讓搬磚之余,有更多的樂趣片吊。
github地址https://github.com/meiniepan/Pic2Ascii

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末绽昏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子俏脊,更是在濱河造成了極大的恐慌全谤,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爷贫,死亡現(xiàn)場離奇詭異啼县,居然都是意外死亡,警方通過查閱死者的電腦和手機沸久,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門季眷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卷胯,你說我怎么就攤上這事子刮。” “怎么了窑睁?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵挺峡,是天一觀的道長。 經常有香客問我担钮,道長橱赠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任箫津,我火速辦了婚禮狭姨,結果婚禮上,老公的妹妹穿的比我還像新娘苏遥。我一直安慰自己饼拍,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布田炭。 她就那樣靜靜地躺著师抄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪教硫。 梳的紋絲不亂的頭發(fā)上叨吮,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天辆布,我揣著相機與錄音,去河邊找鬼茶鉴。 笑死锋玲,一個胖子當著我的面吹牛,可吹牛的內容都是我干的蛤铜。 我是一名探鬼主播嫩絮,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼围肥!你這毒婦竟也來了剿干?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤穆刻,失蹤者是張志新(化名)和其女友劉穎置尔,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氢伟,經...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡榜轿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了朵锣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谬盐。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖诚些,靈堂內的尸體忽然破棺而出飞傀,到底是詐尸還是另有隱情,我是刑警寧澤诬烹,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布砸烦,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜绞幌,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盖溺。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽马僻。三九已至,卻和暖如春注服,著一層夾襖步出監(jiān)牢的瞬間韭邓,已是汗流浹背措近。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留女淑,地道東北人瞭郑。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像鸭你,于是被迫代替她去往敵國和親屈张。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內容