android比例位图性能

Dro*_*oid 8 android canvas bitmap

我有这个:

paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);

sm = new Matrix();
sm.setScale(scale, scale);

private Bitmap getImage(String n) {
    File dir = context.getDir("theme", Context.MODE_PRIVATE);
    File file = new File(dir, n + ".png");
    if (file.exists()) {
       return BitmapFactory.decodeFile(file.getAbsolutePath());
    } else {
        return BitmapFactory.decodeResource(getResources(), getResources().getIdentifier(n, "drawable", getPackageName()));
    }
}

private Bitmap resizeImage(Bitmap b) {
    return Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), sm, true);
}

public void onTouchEvent(MotionEvent event) {
    #scrollable bitmaps, parallax effect
    updatePosition();
}

private void draw() {
    current_time = System.currentTimeMillis();
    if (current_time - last_update_time >= 25) {
        SurfaceHolder holder = getSurfaceHolder();
        Canvas c = null;
        try {
            c = holder.lockCanvas();
            if (c != null) {
                c.drawBitmap(bitmap1, bitmap1_x, bitmap1_y, paint);
                c.drawBitmap(bitmap2, bitmap2_x, bitmap2_y, paint);
                ...
                c.drawBitmap(bitmap20, bitmap20_x, bitmap20_y, paint);
            }
        } finally {
            if (c != null)
                holder.unlockCanvasAndPost(c);
        }
        last_update_time = current_time;
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在调整图像大小,而不是更小.

  1. 没有调整大小,效果很好,性能100%

    bitmap1 = getImage("bitmap1"); ... bitmap20 = getImage("bitmap20");

  2. 调整大小,性能80%

    bitmap1 = getImage("bitmap1"); ... bitmap20 = getImage("bitmap20");

    called once, when screen width and height are known bitmap1 = resizeImage(bitmap1); ... bitmap20 = resizeImage(bitmap20);

  3. 无需调整大小,画布比例,性能40%

    bitmap1 = getImage("bitmap1"); ... bitmap20 = getImage("bitmap20");

    set canvas.scale(scale, scale) inside draw() method

我知道有一些框架像libgdx调整图像大小而不会失去性能,但我使用的是原生画布.

问题:如何以100%的性能绘制已调整大小的图像?

更新 试图制作最小样本.

mWallpaperService.java

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.BatteryManager;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.service.wallpaper.WallpaperService;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.Scroller;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class mWallpaperService extends WallpaperService {

    @Override
    public Engine onCreateEngine() {
        return new mEngine();
    }

    private class mEngine extends Engine {
        private final Handler handler = new Handler();
        private final Runnable drawRunner = new Runnable() {
            @Override
            public void run() {
                draw();
            }

        };

        private Context context;
        private Paint paint;
        private boolean visible = true;
        private boolean draw = true;

        private int width, height;
        private float scale;

        private float begin_x, move_x;
        private int touch_cnt = 0;

        private int bg_max_x;
        private Bitmap bg1, bg2, bg3, bg4..., bg20;
        private float bg1_x, bg1_x2, bg2_x, bg3_x, bg4_x..., bg20_x;
        private float bg1_y, bg2_y, bg3_y, bg4_y..., bg20_y;
        private float bg2_pr, bg3_pr, bg3_pr..., bg20_pr;
        private float bg1_offset_x, bg2_offset_x, bg3_offset_x, bg4_offset_x..., bg20_offset_x;


        private long current_time;
        private long last_update_time;
        private Matrix sm;
        Scroller mScroller;

        public mEngine() {
            context = getApplicationContext();
            mScroller = new Scroller(context);

            bg1 = getImage("bg1");
            bg2 = getImage("bg2");
            bg3 = getImage("bg3");
            bg4 = getImage("bg4");
            ...
            bg20 = getImage("bg20");

            handler.post(drawRunner);
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            this.visible = visible;
            if (visible) {
                draw = true;
                handler.post(drawRunner);
            } else {
                draw = false;
                handler.removeCallbacks(drawRunner);
            }
        }


        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            this.visible = false;
            handler.removeCallbacks(drawRunner);
        }

        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            if (this.width != width && this.height != height) {
                scale = (float) height / bg1.getHeight();
                this.width = width;
                this.height = height;

                sm = new Matrix();
                sm.setScale(scale, scale);

                bg1 = resizeImage(bg1);
                bg2 = resizeImage(bg2);
                bg3 = resizeImage(bg3);
                bg4 = resizeImage(bg4);
                ...
                bg20 = resizeImage(bg20);

                bg_max_x = bg1.getWidth() - width;
                bg1_x = bg_max_x / 2;
                bg1_y = 0;

                #scroll_speed getting from preferences, 0.1f - 1f
                scroll_length = bg_max_x * scroll_speed;

                mScroller.setFinalX((int) bg1_x);
                mScroller.abortAnimation();

                bg2_pr = 0.2f;
                bg2_offset_x = width / 2 - bg2.getWidth() / 2 + bg1_x * bg2_pr;
                bg2_y = height - bg2.getHeight();

                bg3_pr = 0.3f;
                bg3_offset_x = width / 2 - bg3.getWidth() / 2 + bg1_x * bg3_pr;
                bg3_y = height - bg3.getHeight();

                bg4_pr = 0.4f;
                bg4_offset_x = width / 2 - bg4.getWidth() / 2 + bg1_x * bg4_pr;
                bg4_y = height - bg4.getHeight();
                ...

                updatePosition();
            }

            super.onSurfaceChanged(holder, format, width, height);
        }

        private void updatePosition() {
            bg2_x = bg2_offset_x - bg1_x * bg2_pr;
            bg3_x = bg3_offset_x - bg1_x * bg3_pr;
            bg4_x = bg4_offset_x - bg1_x * bg4_pr;
            ...
            bg20_x = bg20_offset_x - bg1_x * bg20_pr;
        }

        @Override
        public void onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    begin_x = event.getX();
                    move_x = 0;
                    touch_cnt = 0;
                    break;
                case MotionEvent.ACTION_UP:
                    x = event.getX();
                    if (touch_cnt >= 1)
                        fling();
                    break;
                case MotionEvent.ACTION_MOVE:
                    x = event.getX();
                    touch_cnt++;
                    //TODO drag
                    break;
            }
        }

        private boolean fling() {
            if (!mScroller.isFinished()) {
                mScroller.forceFinished(true);
            }
            if (move_x != 0) {
                bg1_x2 = mScroller.getCurrX() + move_x;
                if (bg1_x2 <= 0) {
                    bg1_x2 = 0;
                } else if (bg1_x2 > bg_max_x) {
                    bg1_x2 = bg_max_x;
                }

                if (bg1_x != bg1_x2) {
                    mScroller.fling(mScroller.getCurrX(), (int) bg1_y, -(int) (bg1_x > bg1_x2 ? 10000 : -10000), 0, mScroller.getCurrX() - scroll_length <= 0 ? 0 : (int) (mScroller.getCurrX() - scroll_length), mScroller.getCurrX() + scroll_length >= bg_max_x ? bg_max_x : (int) (mScroller.getCurrX() + scroll_length), 0, bg1.getHeight());
                    return true;
                }
            }
            return false;
        }

        private void draw() {
            current_time = System.currentTimeMillis();

            if (mScroller.computeScrollOffset()) {
                bg1_x = mScroller.getCurrX();
                updatePosition();
                draw = true;
            }

            if (draw && current_time - last_update_time >= 25) {
                SurfaceHolder holder = getSurfaceHolder();
                Canvas c = null;
                try {
                    c = holder.lockCanvas();
                    if (c != null) {
                        c.drawBitmap(bg1, -bg1_x, bg1_y, null);
                        c.drawBitmap(bg2, bg2_x, bg2_y, null);
                        c.drawBitmap(bg3, bg3_x, bg3_y, null);
                        c.drawBitmap(bg4, bg4_x, bg4_y, null);
                        ...
                        c.drawBitmap(bg20, bg20_x, bg20_y, null);
                    }
                } finally {
                    if (c != null)
                        holder.unlockCanvasAndPost(c);
                }
                last_update_time = current_time;
                draw = false;
            }

            handler.removeCallbacks(drawRunner);
            if (visible) {
                handler.postDelayed(drawRunner, 1);
            }
        }


        private Bitmap resizeImage(Bitmap b) {
            return Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), sm, true);
        }

        private Bitmap getImage(String n) {
            File dir = context.getDir("theme", Context.MODE_PRIVATE);
            File file = new File(dir, n + ".png");
            if (file.exists()) {
                return BitmapFactory.decodeFile(file.getAbsolutePath());
            } else {
                return BitmapFactory.decodeResource(getResources(), getResources().getIdentifier(n, "drawable", getPackageName()));
            }
        }

        @Override
        public void onDestroy() {
            bg1.recycle();
            bg2.recycle();
            ...
            bg20.recycle();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

MainActivity.java

import android.app.Activity;
import android.app.WallpaperManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;


public class MainActivity extends Activity {
    Intent service;

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

        service = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
        service.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, new ComponentName(this, mWallpaperService.class));
        service.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

        startActivity(service);
        finish();
    }

    #button click
    public void openService(View view) {
        startActivity(service);
        finish();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}
Run Code Online (Sandbox Code Playgroud)

Ido*_*veh 1

如果我确实理解您的问题,那么我认为此链接可能会有所帮助:/sf/answers/297519561/