Android 内存抖动 性能分析 <10>

最近刚好做图形处理方面,对图片像素进行处理,可想而知,一张图片如800*800的,那么像素点就有640000个,如果对这么大的一个数据进行运算操作,将会消耗大量内存空间,下面是自己在处理一张图片,让这张图片调整成一张老照片效果,具体操作如下:

<1> : 新建Android工程如下:

Android 内存抖动 性能分析 <10>_第1张图片


<2> : 工程里面还有其他的代码,这里只给出主要涉及的:

DurianMainActivity.java

package org.durian.duriangaussian;

import android.app.Activity;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;


public class DurianMainActivity extends Activity {

    private ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.durian_main);

        imageView=(ImageView)findViewById(R.id.image);
        imageView.setImageBitmap(BitmapFactory.decodeResource(this.getResources(),R.drawable.ghh));


    }

}

DurianGaussView.java

package org.durian.duriangaussian;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * Created by Administrator on 2016/1/8.
 */
public class DurianGaussView extends View {

    private final static String TAG = "DurianGaussView";

    private Bitmap mBitmap;
    private Bitmap mOldPhotoMap;

    private int mBitmapWidth;
    private int mBitmapHeight;

    private int mArrayColorLength;
    private int mArrayColor[] = null;

    private int mInColors[] = null;
    private int mOutColors[] = null;

    private int count = 0;

    private Context mContext;

    public DurianGaussView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initView(context);

    }

    private void initView(Context context) {

        mContext=context;
        mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ghh);
        mBrightnessBitmap.execute();

        mOldPhotoMap= BitmapFactory.decodeResource(context.getResources(), R.drawable.ghh);
        mOldPhotoEffort.execute();



    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int index=0;

//        canvas.drawBitmap(mBitmap,25.0f,25.0f,null);
        canvas.drawBitmap(mOldPhotoMap,500f,25.0f,null);

        /*for (int i = 0; i < 100; i++) {

            int x = i - 50;
            double y = Gauss.gaussFormula(x / 10);

        }*/

    }

    private Handler mHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            Log.i(TAG,"message what : " +msg.what);

            invalidate();

        }
    };

    private OldPhotoEffort mOldPhotoEffort=new OldPhotoEffort();
    private class OldPhotoEffort extends AsyncTask<String,Integer,String>{
        @Override
        protected String doInBackground(String... params) {

            Log.i(TAG,"OldPhotoEffort : ...");
            mOldPhotoMap=DurianOldPhotoEffort.makeOldPhotoEffort(mContext);
            mHandler.sendEmptyMessage(100);
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

    }

    private BrightnessBitmap mBrightnessBitmap=new BrightnessBitmap();
    private class BrightnessBitmap extends AsyncTask<String,Integer,String>{

        @Override
        protected String doInBackground(String... params) {

//            mBitmap=DurianBrightness.decodeBitmap(mContext);
            mHandler.sendEmptyMessage(0);
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }
    }

}

上面有两个工作线程,这里屏蔽其中一个功能.

DurianOldPhotoEffort.java

package org.durian.duriangaussian;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

/**
 * Created by Administrator on 2016/1/13.
 */
public class DurianOldPhotoEffort {

    private final static String TAG="DurianOldPhotoEffort";

    public static Bitmap makeOldPhotoEffort(Context context){

        Bitmap bitmap= BitmapFactory.decodeResource(context.getResources(),R.drawable.ghh);

        int bitmapWidth=bitmap.getWidth();
        int bitmapHeight=bitmap.getHeight();
        int pixLength=bitmapHeight*bitmapWidth;

        int inPixs[]=new int[pixLength];
        int outPixs[]=new int[pixLength];

        int tr=0,tg=0,tb=0,ta=0;
        int index=0;

        int color=0;

        Log.i(TAG, "123**********************");

        for (int row=0;row<bitmapHeight;row++){

            for (int col=0;col<bitmapWidth;col++){
                index=row*bitmapWidth+col;

                color=bitmap.getPixel(col,row);
                inPixs[index]=color;

            }

        }

        Log.i(TAG, "456**********************");

        int fr=0,fg=0,fb=0;
        int rows=0,cols=0;
        for (rows=0;rows<bitmapHeight;rows++){

            tr=0;tg=0;tb=0;ta=0;
            for (cols=0;cols<bitmapWidth;cols++){
                index=rows*bitmapWidth+cols;

                ta=(inPixs[index]>>24) & 0xFF;
                tr=(inPixs[index]>>16) & 0xFF;
                tg=(inPixs[index]>>8) & 0xFF;
                tb=(inPixs[index]) & 0xFF;

                //
                /*int fr=(int)colorBlend(noise(),(tr*0.393)+(tg*0.769)+(tb*0.189),tr);
                int fg=(int)colorBlend(noise(),(tr*0.349)+(tg*0.686)+(tb*0.168),tg);
                int fb=(int)colorBlend(noise(),(tr*0.272)+(tg*0.534)+(tb*0.131),tb);*/

                fr=(int)colorBlend(noise(),(tr*0.393)+(tg*0.769)+(tb*0.189),tr);
                fg=(int)colorBlend(noise(),(tr*0.349)+(tg*0.686)+(tb*0.168),tg);
                fb=(int)colorBlend(noise(),(tr*0.272)+(tg*0.534)+(tb*0.131),tb);

                outPixs[index]=(ta<<24) | (clamp(fr)<<16) | (clamp(fg)<<8) | clamp(fb);

                bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

                bitmap.setPixel(cols,rows,outPixs[index]);

            }

        }

        Log.i(TAG, "789**********************");

        return bitmap;

    };

    private static double noise(){
        return Math.random()*0.5+0.5;
    }

    private static double colorBlend(double scale,double dest,double src){
        return (scale*dest+(1.0-scale)*src);
    }

    private static int clamp(int c){
        return c>255?255:((c<0)?0:c);
    }

    public String toString(){
        return "Effect from Photoshop App !";
    }

}

布局文件:

<LinearLayout 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"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <org.durian.duriangaussian.DurianGaussView
        android:id="@+id/durianview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>


里面用到的图片:



<3> : 运行的结果,图片将不会被处理,控制台一直报:

01-14 00:45:27.745  15021-15036/org.durian.duriangaussian I/art﹕ Background partial concurrent mark sweep GC freed 30(1200B) AllocSpace objects, 11(24MB) LOS objects, 33% free, 32MB/48MB, paused 6.652ms total 35.034ms


<4> : 内存图:

Android 内存抖动 性能分析 <10>_第2张图片

右上角的Free和Allocated 旁边内存量大小将不断的变化,从上面的图形来看,内存抖动的非常厉害.

<5> : 解决上面的内存抖动,首先想到的是可能是下面导致的:

//用注释部分的,将会导致内存疯狂抖动
                /*int fr=(int)colorBlend(noise(),(tr*0.393)+(tg*0.769)+(tb*0.189),tr);
                int fg=(int)colorBlend(noise(),(tr*0.349)+(tg*0.686)+(tb*0.168),tg);
                int fb=(int)colorBlend(noise(),(tr*0.272)+(tg*0.534)+(tb*0.131),tb);*/

                //但是由于下面运算量,还是会疯狂抖动
                fr=(int)colorBlend(noise(),(tr*0.393)+(tg*0.769)+(tb*0.189),tr);
                fg=(int)colorBlend(noise(),(tr*0.349)+(tg*0.686)+(tb*0.168),tg);
                fb=(int)colorBlend(noise(),(tr*0.272)+(tg*0.534)+(tb*0.131),tb);

所以把这里和相关的代码全部用到fr,fg等地方全部屏蔽掉,但是再次运行的时候发现还是不行.

继续查找:

bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

                bitmap.setPixel(cols,rows,outPixs[index]);
发现这段代码的确有问题,bitmap反复copy,我靠,有点低级错误呀.看来需要把这一句代码放在for循环外面:

bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

调整为:

Log.i(TAG, "456**********************");

        int fr=0,fg=0,fb=0;
        int rows=0,cols=0;
        bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
        for (rows=0;rows<bitmapHeight;rows++){

            tr=0;tg=0;tb=0;ta=0;
            for (cols=0;cols<bitmapWidth;cols++){
                index=rows*bitmapWidth+cols;

                ta=(inPixs[index]>>24) & 0xFF;
                tr=(inPixs[index]>>16) & 0xFF;
                tg=(inPixs[index]>>8) & 0xFF;
                tb=(inPixs[index]) & 0xFF;

                fr=(int)colorBlend(noise(),(tr*0.393)+(tg*0.769)+(tb*0.189),tr);
                fg=(int)colorBlend(noise(),(tr*0.349)+(tg*0.686)+(tb*0.168),tg);
                fb=(int)colorBlend(noise(),(tr*0.272)+(tg*0.534)+(tb*0.131),tb);

                outPixs[index]=(ta<<24) | (clamp(fr)<<16) | (clamp(fg)<<8) | clamp(fb);

                bitmap.setPixel(cols,rows,outPixs[index]);

            }

        }

        Log.i(TAG, "789**********************");

然后再重新运行:

Android 内存抖动 性能分析 <10>_第3张图片

好了问题就解决了,一行代码之差.

整个app运行效果:


左上角是没有调整的原图,下面是经过处理过的,照片发黄的效果了.











你可能感兴趣的:(Android 内存抖动 性能分析 <10>)