<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android實(shí)現(xiàn)圖片轉(zhuǎn)字符畫效果

          共 3284字,需瀏覽 7分鐘

           ·

          2021-11-18 07:56


          作者:kinton
          來(lái)源:https://www.jianshu.com/p/16ef3bf9ac5c


          開門見山!先上效果圖:



          原圖



          轉(zhuǎn)換字符畫

          字符稍微密集了一點(diǎn),不過放大來(lái)看大家應(yīng)該能夠看到確確實(shí)實(shí)是字符畫。
          那我們?cè)诎沧慷耸侨绾螌?shí)現(xiàn)?
          Android開發(fā)中對(duì)圖片的操作,顯示一般都是通過Bitmap進(jìn)行的,我們可以通過圖片路徑獲取Bitmap對(duì)象:

          1static?public?Bitmap?getBitmapByUri(Context?context,?Uri?uri)?{
          2????????Bitmap?bit?=?null;
          3????????try?{
          4????????????bit?=?BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri));
          5????????}?catch?(Exception?ex)?{
          6????????????Log.i("utils",?""?+?ex.getMessage());
          7????????}
          8????????return?bit;
          9????}

          一個(gè)圖片的每一個(gè)像素其實(shí)都是一個(gè)值,這個(gè)值代表著這個(gè)像素的顏色,我們可以通過位運(yùn)算來(lái)獲取這個(gè)像素的ARGB值。
          在安卓開發(fā)中要獲取一個(gè)圖片的每一個(gè)像素值其實(shí)很簡(jiǎn)單:

          1//按照參數(shù)范圍獲取像素?cái)?shù)組
          2bitmap.getPixels(...);
          3//或者獲取單個(gè)位置像素
          4bitmap.getPixel(x,y);

          當(dāng)我們獲取到了像素值,轉(zhuǎn)換成ARGB值后,我們獲取帶了RGB三個(gè)值,要如何判斷什么顏色用什么字?要知道調(diào)色輪盤的顏色數(shù)不勝數(shù):



          截取自iconfont的調(diào)色板

          這么多的顏色我們應(yīng)該用什么樣的標(biāo)準(zhǔn)給這么多顏色歸類?灰度值是個(gè)很好的辦法,什么是灰度值?灰度值的范圍只有0到255,計(jì)算方式一般是RGB三個(gè)值的平均值(也可以通過對(duì)RGB值進(jìn)行加權(quán)計(jì)算不同的灰度),在很多圖像處理里面的圖片灰度化步驟用的就是這種方法。



          灰度化示例(轉(zhuǎn)自百度百科圖片)

          原理跟思路清楚了,我們實(shí)現(xiàn)下把Bitmap轉(zhuǎn)化成灰度值數(shù)組的方法:

           1?static?public?int[][]?getBitmap2GaryArray(Bitmap?bitmap)?{
          2????????int?width?=?bitmap.getWidth();????????????//獲取位圖的寬
          3????????int?height?=?bitmap.getHeight();????????//獲取位圖的高
          4????????int[][]?datas?=?new?int[width][height];????//通過位圖的大小創(chuàng)建像素點(diǎn)數(shù)組
          5????????//也可以使用getPixels方法來(lái)獲取像素?cái)?shù)組
          6????????//bitmap.getPixels(datas,?0,?width,?0,?0,?width,?height);
          7????????int?alpha?=?0xFF?<24;
          8????????bitmap.getPixels();
          9????????for?(int?i?=?0;?i?width;?i++)?{
          10????????????for?(int?j?=?0;?j?height;?j++)?{
          11????????????????int?grey?=?bitmap.getPixel(i,?j);
          12????????????????int?red?=?(grey?&?0x00ff0000)?>>?16;?//取高兩位
          13????????????????int?green?=?(grey?&?0x0000ff00)?>>?8;?//取中兩位
          14????????????????int?blue?=?grey?&?0x000000ff;?//取低兩位
          15
          16????????????????grey?=?(int)?((float)?red?*?0.4?+?(float)?green?*?0.3?+?(float)?blue?*?0.3);
          17????????????????datas[i][j]?=?grey;
          18????????????}
          19????????}
          20????????return?datas;
          21????}

          在獲取像素前我們還需要多做一步,為了防止圖片過大(類似2K圖/4K圖),我們需要在獲取像素前做一次統(tǒng)一標(biāo)準(zhǔn)化的壓縮,我設(shè)置為寬為200,高等比例壓縮。

           1...
          2//寬為200時(shí),計(jì)算壓縮比例是多少
          3float?xScale?=?(float)?200?/?bitmap.getWidth();
          4bitmap?=?BitmapUtils.compressBitmap(bitmap,?xScale,?xScale);
          5...
          6
          7static?public?Bitmap?compressBitmap(Bitmap?bitmap,?float?sx,?float?sy)?{
          8????????Matrix?matrix?=?new?Matrix();
          9????????matrix.setScale(sx,?sy);
          10????????Log.i("utils_compressBitmap",?""?+?sx?+?","?+?sy);
          11????????Bitmap?bit?=?Bitmap.createBitmap(bitmap,?0,?0,?bitmap.getWidth(),
          12????????????????bitmap.getHeight(),?matrix,?true);
          13
          14????????Log.i("utils_compressBitmap",?""?+?bit.getWidth()?+?","?+?bit.getHeight());
          15????????//記得把不用的bitmap進(jìn)行回收,以防止OOM
          16????????bitmap.recycle();
          17????????return?bit;
          18????}

          當(dāng)我們通過壓縮好的圖片獲取到了它的灰度值數(shù)組,現(xiàn)在我們就可以根據(jù)灰度值轉(zhuǎn)換為對(duì)應(yīng)的文字了,我給了灰度值15個(gè)等級(jí),根據(jù)顏色的深度給對(duì)應(yīng)的中文字:(0是黑色,255是白色)

          1static?String[]?arr?=?{"餮",?"淼",?"圓",?"困",?"品",?"回",?"田",?"凸",?"口",?"王",?"天",?"干",?"工",?"十",?"一"};

          我們制定好字符等級(jí),那么要怎么根據(jù)數(shù)組制作圖片呢?
          上面說(shuō)過圖片的操作在Android中一般都在Bitmap進(jìn)行的,所以我們要想繪制一張新的圖片,那么就創(chuàng)建一個(gè)新的Bitmap對(duì)象,繪制的事情交給萬(wàn)能的畫布就好了,畫布帶有文字繪制接口完美的符合我們需求:

           1static?public?Bitmap?array2Bitmap(int[][]?garyDatas,?int?width,?int?height)?{
          2????????//繪制一個(gè)字對(duì)應(yīng)一個(gè)像素,所以新繪制的Bitmap的大小應(yīng)該乘上字體大小
          3????????Bitmap?whiteBgBitmap?=?Bitmap.createBitmap(width?*?6?+?20,?height?*?6?+?20,?Bitmap.Config.ARGB_8888);
          4????????//在Bitmap上創(chuàng)建畫布
          5????????Canvas?canvas?=?new?Canvas(whiteBgBitmap);
          6????????//繪制白色背景
          7????????canvas.drawARGB(255,?255,?255,?255);
          8????????//初始化畫筆
          9????????Paint?mPaint?=?new?Paint();
          10????????mPaint.setStrokeWidth(1);
          11????????mPaint.setColor(Color.BLACK);
          12????????mPaint.setTextSize(6);
          13
          14????????int?x?=?0;
          15?????????//遍歷灰度值數(shù)組
          16????????for?(int?xIndex?=?10;?x?6)?{
          17????????????int?y?=?0;
          18????????????for?(int?yIndex?=?10;?y?6)?{
          19????????????????//獲取灰度值對(duì)應(yīng)的字符
          20????????????????int?charIndex?=?garyDatas[x][y]?/?18;
          21????????????????String?_char?=?arr[charIndex];
          22????????????????//在對(duì)應(yīng)的坐標(biāo)繪制字符
          23????????????????canvas.drawText(_char,?xIndex,?yIndex,?mPaint);
          24????????????????y++;
          25????????????}
          26????????????x++;
          27????????}
          28????????return?whiteBgBitmap;
          29????}

          繪制完成后輸出Bitmap,下一步是把Bitmap保存為本地圖片,關(guān)鍵代碼如下:

           1...
          2File?photo?=?new?File(Environment.getExternalStorageDirectory()?+?"/"?+?dirName,?String.format("CharPic_%d.jpg",System.currentTimeMillis()));
          3
          4File?dir?=?new?File(photo.getParent());
          5if(!dir.exists()){
          6??????dir.mkdirs();
          7?}
          8photo.createNewFile();
          9saveBitmapToJPG(bmp,?photo);
          10...
          11
          12static?private?void?saveBitmapToJPG(Bitmap?bitmap,?File?photo)?throws?IOException?{
          13????????OutputStream?stream?=?new?FileOutputStream(photo);
          14????????bitmap.compress(Bitmap.CompressFormat.JPEG,?80,?stream);
          15????????stream.close();
          16????????bitmap.recycle();
          17????}

          下一步我們?yōu)榱嗽谙到y(tǒng)相冊(cè)更好的找到我們的圖片,我們可以把圖片發(fā)送一個(gè)廣播來(lái)通知系統(tǒng)相冊(cè):

          1Intent?mediaScanIntent?=?new?Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
          2Uri?contentUri?=?Uri.fromFile(photo);
          3mediaScanIntent.setData(contentUri);
          4context.sendBroadcast(mediaScanIntent);

          以上就是圖片轉(zhuǎn)成字符畫的全部代碼與講解??赡苡械娜藭?huì)問這樣的功能,除了酷炫,有趣,牛逼之外,做出來(lái)有什么用?我只能問得好!乍一看好像用處不大,但是基于這個(gè)功能我們可以做短視頻轉(zhuǎn)換字符畫視頻。下一篇我將會(huì)講一下如何把視頻轉(zhuǎn)換成字符畫視頻,本篇的內(nèi)容到此為止,如有問題,歡迎提出,如有錯(cuò)誤,歡迎指正,謝謝。

          奉上完整的源碼(已完成視頻轉(zhuǎn)換跟圖片轉(zhuǎn)換功能),覺得有趣的請(qǐng)star一下唄。
          完整項(xiàng)目源碼地址:https://github.com/452kinton/CharacterDance




          ? 耗時(shí)2年,Android進(jìn)階三部曲第三部《Android進(jìn)階指北》出版!

          ? 『BATcoder』做了多年安卓還沒編譯過源碼?一個(gè)視頻帶你玩轉(zhuǎn)!

          ? 『BATcoder』我去!安裝Ubuntu還有坑?

          ? 重生!進(jìn)階三部曲第一部《Android進(jìn)階之光》第2版 出版!


          ?BATcoder技術(shù)群,讓一部分人先進(jìn)大廠

          大家,我是劉望舒,騰訊TVP,著有三本業(yè)內(nèi)知名暢銷書,連續(xù)四年蟬聯(lián)電子工業(yè)出版社年度優(yōu)秀作者,百度百科收錄的資深技術(shù)專家。


          想要加入?BATcoder技術(shù)群,公號(hào)回復(fù)BAT?即可。

          為了防止失聯(lián),歡迎關(guān)注我的小號(hào)

          ??微信改了推送機(jī)制,真愛請(qǐng)星標(biāo)本公號(hào)??
          瀏覽 72
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一区二区黄色片 | av无码精品一区二区三区宅噜噜 | 欧美黄片一区 | 操逼无码免费 | 日韩中文字幕视频在线 |