話說天下分久必合,合久必分。大諾王朝內閣首輔康培凱康大學士,剛愎自用,固步自封,不思進取,致使天下群雄並起。亂世之中,世家門閥Apple,微軟盡攬朝中精英於門下。而新進貴族Google則營前插著兩面大旗,只見左邊那面用西文寫著“I am free”,右面則用漢字寫著“你懂的”。至此,江湖好漢莫不相投與此。在這個修道不如修Bug的年代,貧道也只有順應時代的潮流,開始了兩點一線的Android開發碼工生活。
雖然Android秉承了太祖的團結一切可以團結的力量平民哲學思想,但是他終歸出生於貴族家庭。帶著一點小傲嬌,有點不接地氣兒。
話說,一個風和日麗的早春上午,貧道剛結束了一個編輯圖片功能的階段開發,在QQ上和眾道友們激揚文字,指點江山,縱談當前天下大勢。談到精彩之處,貧道不禁輕搖手中免費發放的時代報,頗有當年武侯隆中對的氣勢,好不得意。突然叮噹一聲,只見螢幕右下角,彈出個郵件提示框,貧道一看是一封Bug報告信。頓時,剛才的好心情一鬨而散,然後很不情願地點開了報告連結,只見上面寫著Image is destroyed。貧道頭上一陣黑線,用人類的正常思維實在想不出Image is destroyed的是個什麼狀況。還好該測試人士給出了一張展示bug的圖片,點進去一看,又是一陣惡寒。只見滿屏的馬賽克充斥其中,貧道暗想,雖然是測試,也不能這樣假公濟私,蹭機瀏覽收整合人專用圖片。而且這得多暴露啊,滿屏的馬賽克,想到這貧道暗暗鄙視了一下這個測試人員,好歹拿一張馬賽克美女圖啥的,給大家樂一下。獨樂樂,不如眾樂樂嘛。此時貧道故作鎮定地向測試員問起了該bug的情況,結果卻得到了一個驚人的訊息,此馬賽克並非天然形成,而是經過了圖片的載入,編輯,儲存,再載入,編輯,儲存,如此大小周天往複幾次,就成了這個效果。聽到這,貧道暗歎連連,趕忙拿了測試圖片,開始找尋原因。
回到座位點開圖片一看,是一個只比呂布智商高了20的傢伙,號稱只吃涮羊肉的灰太狼像(見圖1)。在貧道旋轉,上下左右顛倒,剪下等一系列的操作後,的確一層似曾相識的薄馬賽克浮現了出來(見圖2)。
圖1 圖2
難道是圖片繪製時不夠精確?根據平常玩遊戲的經驗,調用了Paint的setAntiAlias反鋸齒函數來提高繪畫品質。然後籌措滿志的按下了Run,但是殘酷的現實打破了貧道妄圖速戰速決的期望。馬賽克君如同小強附體,頑強的生存了下來。
貧道再次審視了代碼,又做出一個判斷,是否是圖片旋轉或者上下左右顛倒時,座標移動的誤差積累所引起的呢?在忍痛割捨了旋轉和顛倒功能後,再一次Run了下程式,濤聲依舊。
難道是圖片的顏色位元問題,但一看代碼,都是四個8(Config.ARGB_8888),好吉利的設定。
常言說的好,欲使其滅亡,必先使其瘋狂。貧道重新寫了個測試程式(見以下的程式碼)。屏蔽了所有的編輯效果,只保留了載入和儲存。在惡狠狠地按下了Run後,貧道的世界觀開始崩潰了。馬賽克君巋然不動,好似老中醫的小廣告似的牢牢的貼在了圖片上。
MainActivity.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="fitCenter" /></RelativeLayout>
MainActivity.java
package com.example.testcompress;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileOutputStream;import android.os.Bundle;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Bitmap.CompressFormat;import android.view.Menu;import android.widget.ImageView;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Bitmap bmp = BitmapFactory.decodeFile("/mnt/sdcard/wolf.jpg");for(int i = 0 ; i < 30 ; i++){ImageView mv = (ImageView)findViewById(R.id.img);mv.setImageBitmap(bmp);File file = null;try {file = new File("/mnt/sdcard/wolf_tmp.jpg");file.delete();ByteArrayOutputStream stream = new ByteArrayOutputStream();bmp.compress(CompressFormat.JPEG, 100, stream);FileOutputStream os = new FileOutputStream(file);os.write(stream.toByteArray());os.close();} catch (Exception ex) {file = null;}bmp = BitmapFactory.decodeFile("/mnt/sdcard/wolf_tmp.jpg");}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.activity_main, menu);return true;}}
貧道雙手撓頭,陷入了沉思中。就在漫天的飛屑鋪滿案頭的時候,貧道突然發現,灰太狼這貨居然是裸奔的,難道被SDK判斷為少兒不宜,需要做騎兵處理。於是立馬換成了老少皆宜的desert.jpg檔案(見圖3)。事實證明我們又一次低估了馬賽克君的無恥程度,這次滄桑無垠的沙漠獲得了和蒼老師一樣的待遇,漫天的馬賽克(見圖4)。
圖3 圖4
這時旁邊同事的電腦又傳來了“我相信真相只有一個”那熟悉的聲音。腦海裡頓時出現貌似忠良,實乃國賊的秦檜,嚴嵩,汪Data Replication System形象。漸漸這些名字逐漸匯聚為compress的字樣。沒錯最終的元兇就是這個貌似二師兄,實乃佛地魔的Bitmap.compress。在屢次的儲存中,由於jpg壓縮演算法的問題,隨著儲存次數的增加,導致像素丟失越來越嚴重,最後馬賽克化。再狡猾的狐狸還是鬥不過獵人,貧道對著網頁中的Google標誌,鄙視的朝下豎起了大拇指。
為了再踩上一萬隻腳,我又測試了下png格式(修改代碼如下)。同樣都是一個媽生的,PNG圖片幾乎無損(見圖5)。
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Bitmap bmp = BitmapFactory.decodeFile("/mnt/sdcard/wolf.png");for(int i = 0 ; i < 30 ; i++){ImageView mv = (ImageView)findViewById(R.id.img);mv.setImageBitmap(bmp);File file = null;try {file = new File("/mnt/sdcard/wolf_tmp.png");file.delete();ByteArrayOutputStream stream = new ByteArrayOutputStream();bmp.compress(CompressFormat.PNG, 100, stream);FileOutputStream os = new FileOutputStream(file);os.write(stream.toByteArray());os.close();} catch (Exception ex) {file = null;}bmp = BitmapFactory.decodeFile("/mnt/sdcard/wolf_tmp.png");}}
圖5
所以在此,貧道友情提示一下,為了保持圖的還原度,在Android開發中請盡量使用PNG格式圖片,日本國圖片除外。同時也將此提示寫在了中午用過的餐巾紙上,裱糊後,與諸君共勉。