傲娇Android二三事之天不长地不久的Bitmap.compress

话说天下分久必合,合久必分。大诺王朝内阁首辅康培凯康大学士,刚愎自用,固步自封,不思进取,致使天下群雄并起。乱世之中,世家门阀Apple,微软尽揽朝中精英于门下。而新进贵族Google则营前插着两面大旗,只见左边那面用西文写着“I am free”,右面则用汉字写着“你懂的”。至此,江湖好汉莫不相投与此。在这个修道不如修Bug的年代,贫道也只有顺应时代的潮流,开始了两点一线的Android开发码工生活。

虽然Android秉承了太祖的团结一切可以团结的力量平民哲学思想,但是他终归出生于贵族家庭。带着一点小傲娇,有点不接地气儿。

话说,一个风和日丽的早春上午,贫道刚结束了一个编辑图片功能的阶段开发,在QQ上和众道友们激扬文字,指点江山,纵谈当前天下大势。谈到精彩之处,贫道不禁轻摇手中免费发放的时代报,颇有当年武侯隆中对的气势,好不得意。突然叮当一声,只见屏幕右下角,弹出个邮件提示框,贫道一看是一封Bug报告信。顿时,刚才的好心情一哄而散,然后很不情愿地点开了报告链接,只见上面写着Image is destroyed。贫道头上一阵黑线,用人类的正常思维实在想不出Image is destroyed的是个什么状况。还好该测试人士给出了一张展示bug的图片,点进去一看,又是一阵恶寒。只见满屏的马赛克充斥其中,贫道暗想,虽然是测试,也不能这样假公济私,蹭机浏览收集成人专用图片。而且这得多暴露啊,满屏的马赛克,想到这贫道暗暗鄙视了一下这个测试人员,好歹拿一张马赛克美女图啥的,给大家乐一下。独乐乐,不如众乐乐嘛。此时贫道故作镇定地向测试员问起了该bug的情况,结果却得到了一个惊人的消息,此马赛克并非天然形成,而是经过了图片的载入,编辑,保存,再载入,编辑,保存,如此大小周天往复几次,就成了这个效果。听到这,贫道暗叹连连,赶忙拿了测试图片,开始找寻原因。

回到座位点开图片一看,是一个只比吕布智商高了20的家伙,号称只吃涮羊肉的灰太狼像(见图1)。在贫道旋转,上下左右颠倒,剪切等一系列的操作后,的确一层似曾相识的薄马赛克浮现了出来(见图2)。

傲娇Android二三事之天不长地不久的Bitmap.compress_第1张图片        傲娇Android二三事之天不长地不久的Bitmap.compress_第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 {

	@Override
	protected 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");
			
		}
	}

	@Override
	public 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)。

    傲娇Android二三事之天不长地不久的Bitmap.compress_第3张图片

图3                                                                                                          图4

这时旁边同事的电脑又传来了“我相信真相只有一个”那熟悉的声音。脑海里顿时出现貌似忠良,实乃国贼的秦桧,严嵩,汪精卫形象。渐渐这些名字逐渐汇聚为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格式图片,日本国图片除外。同时也将此提示写在了中午用过的餐巾纸上,裱糊后,与诸君共勉。


此文已在cnblog上同步发表。

 

 

 

 

 

 

 

 
 
 
 
 
 
 
 
 
 
 

你可能感兴趣的:(android,科普)