2

我已经开始使用 android studio beta 学习 android 和 java。作为第一个简单的测试应用程序,我试图让一个基本的 Mandelbrot 渲染器正常工作。我已经让它显示出来了,但现在我想要它更快。任何人都可以就以下问题提供建议吗?

  1. 文档说 canvas.drawbitmap 已折旧。我应该改用什么?在屏幕上显示位图的最快方法是什么?

  2. 如何显示计算进度?如果我取消标记标记为“计算每行后更新显示”的 2 行,则在计算期间没有更新,并且对 canvas.drawbitmap 的额外调用确实减慢了所有速度(79 秒与没有它的 31 秒相比)。

  3. 我能做些什么来加快一般数学调用的速度吗?

对于这个例子,我试图让它尽可能简单。

非常感谢对新手的任何提示。如果可能的话,我不想从一开始就学习坏习惯。

布局有一个与屏幕对齐的图像视图。完整的代码是

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.Display;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;

import java.text.DecimalFormat;
import java.util.Random;
import static android.graphics.Color.argb;
import static android.graphics.Color.rgb;

public class myActivity extends Activity  {

    myView myview;
    Bitmap bmp;
    Canvas myCanvas;
    ImageView img;
    Paint paint;
    Boolean started=false;
    Integer ih,iw,i,redraws,fw,fh;
    long startms,finishms;
    Random rnd;

    double xmin,xmax,ymin,ymax,padding,bailout,bailout_squared,stepx,stepy,x,y,magnitude;
    double realiters,tweenval;
    Integer col,colval1,colval2;
    Integer iterations,maxiterations,superx,supery,samplepixels,square_samplepixels,xloop,yloop;
    double zr,zi,cr,ci,xloopdouble,yloopdouble;
    int[] colorpalette = new int[256];
    int[] pixels;
    int r,g,b,r1,g1,b1,r2,g2,b2,totalr,totalg,totalb;

    private void init(){
        //screen size
        Display display = getWindowManager().getDefaultDisplay();
        Point sizePoint = new Point();
        paint = new Paint();
        display.getSize(sizePoint);
        iw=sizePoint.x;
        ih=sizePoint.y;
        //pixels array
        fw=iw;
        fh=ih;
        pixels=new int[fw*fh];
        //create bitmap
        bmp=Bitmap.createBitmap(iw, ih, Bitmap.Config.RGB_565);
        //create canvas
        myCanvas =new Canvas();
        myCanvas.setBitmap(bmp);
        img = (ImageView) findViewById(R.id.imageView1);
        rnd = new Random();
    }

    // calculates and displays the Mandelbrot fractal
    private void Mandelbrot(){

        startms= SystemClock.uptimeMillis();

        //coordinates
//        xmin=-1.6345100402832;
//        xmax=-1.63043992784288;
//        ymin=-0.00209962230258512;
//        ymax=0.00209259351094558;
        xmin=-2.3;
        xmax=2.3;
        ymin=-2.1;
        ymax=2.1;

        fw=iw;
        fh=ih;

        //adjust coords to match screen aspect
        if (iw<ih) {
            padding=(xmax-xmin)/iw*(ih-iw);
            ymin=ymin-padding/2.0;
            ymax=ymax+padding/2.0;
        } else {
            padding=(ymax-ymin)/ih*(iw-ih);
            xmin=xmin-padding/2.0;
            xmax=xmax+padding/2.0;
        }

        bailout=8.0; //needs to be higher than default 2 for the CPM coloring to be smooth
        bailout_squared=bailout*bailout;
        maxiterations=64;
        samplepixels=1;
        square_samplepixels=samplepixels*samplepixels;

        //random color palette
        for (col=0;col<256;col++){
            colorpalette[col]=android.graphics.Color.argb(255,rnd.nextInt(256),rnd.nextInt(256),rnd.nextInt(256));
        }

        stepx=(xmax-xmin)/fw/samplepixels;
        stepy=(ymax-ymin)/fh/samplepixels;

        for (yloop=0;yloop<fh;yloop++){
            for (xloop=0;xloop<fw;xloop++){

                totalr=0;
                totalg=0;
                totalb=0;
                r=0;
                g=0;
                b=0;
                xloopdouble=(double)xloop;
                yloopdouble=(double)yloop;

                for (supery=0;supery<samplepixels;supery++)
                {
                    for (superx=0;superx<samplepixels;superx++)
                    {
                        cr = xmin+xloopdouble/(double)fw*(xmax-xmin)+(stepx*(double)superx);
                        ci = ymin+yloopdouble/(double)fh*(ymax-ymin)+(stepy*(double)supery);

                        zr = 0.0;
                        zi = 0.0;
                        magnitude=0.0;

                        for(iterations=0; iterations<maxiterations; iterations++)
                        {
                            i=iterations;

                            x = (zr * zr - zi * zi) + cr;
                            y = (zi * zr + zr * zi) + ci;

                            magnitude=(x * x + y * y);
                            if(magnitude>bailout_squared) break;

                            zr = x;
                            zi = y;
                        }

                        if (iterations>=maxiterations) {
                            r=0;
                            g=0;
                            b=0;
                        } else {
                            //CPM smooth colors
                            realiters=iterations+1-((Math.log(Math.log(Math.sqrt(magnitude)))/Math.log(2.0)));
                            colval1=(int) Math.floor(realiters % 255);
                            colval2=(colval1+1) % 255;
                            tweenval=realiters-Math.floor(realiters);
                            r1=Color.red(colorpalette[colval1]);
                            g1=Color.green(colorpalette[colval1]);
                            b1=Color.blue(colorpalette[colval1]);
                            r2=Color.red(colorpalette[colval2]);
                            g2=Color.green(colorpalette[colval2]);
                            b2=Color.blue(colorpalette[colval2]);
                            r=(int) (r1+((r2-r1)*tweenval));
                            g=(int) (g1+((g2-g1)*tweenval));
                            b=(int) (b1+((b2-b1)*tweenval));
                        }
                        totalr=totalr+r;
                        totalg=totalg+g;
                        totalb=totalb+b;
                    }
                }

                r=(int) totalr/square_samplepixels;
                g=(int) totalg/square_samplepixels;
                b=(int) totalb/square_samplepixels;

                //update pixels array
                pixels[xloop+yloop*fw]=rgb(r, g, b);
            }

            //update display after each line has been calculated
            //myCanvas.drawBitmap(pixels,0,fw,0,0,fw,fh,false,null);
            //if (img != null) img.invalidate();
        }

        myCanvas.drawBitmap(pixels,0,fw,0,0,fw,fh,false,null);
        finishms=SystemClock.uptimeMillis();
    }


    private void updateTimeTaken(){
        //turn antialiasing on
        paint.setAntiAlias(true);
        // draw some text using FILL style
        paint.setStyle(Paint.Style.FILL);
        paint.setTextSize(30);

        DecimalFormat myFormatter = new DecimalFormat("#,###,###");

        paint.setColor(Color.BLACK);
        myCanvas.drawText("Time taken = " + myFormatter.format(finishms - startms) + " ms", 15, 45, paint);
        paint.setColor(Color.WHITE);
        myCanvas.drawText("Time taken = " + myFormatter.format(finishms - startms) + " ms", 14, 44, paint);

        paint.setColor(Color.BLACK);
        myCanvas.drawText("Screen size = " + String.valueOf(iw) + " x " + String.valueOf(ih), 15, 85, paint);
        paint.setColor(Color.WHITE);
        myCanvas.drawText("Screen size = " + String.valueOf(iw) + " x " + String.valueOf(ih), 14, 84, paint);

    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        //fullscreen no menu
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        redraws=0;
        super.onCreate(savedInstanceState);
        myview = new myView(this);

        setContentView(myview);

        init();

        started=true;

        Mandelbrot();
        updateTimeTaken();

    }

    private class myView extends View{
        public myView(Context context){
            super(context);
        }

        @Override protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            //draw off screen bitmap to screen
            if (started==true){
                canvas.drawBitmap(bmp,0,0,paint);
            }

        }

    }
}
4

0 回答 0