Рисование растрового изображения происходит медленно при масштабировании до высокого разрешения

У меня есть очень простая задача: нарисовать фоновое изображение в пользовательском представлении. Я создаю растровое изображение и масштабирую его, чтобы оно соответствовало ширине и высоте представления. Это делает приложение намного медленнее, примерно в два раза быстрее (я распечатываю значение времени каждые 10 миллисекунд, чтобы измерить скорость производительности). Это код:

public class GView extends View {

int w, h;
Bitmap bg;
int time = 0;

boolean created = false;
public GView(Context context) {
    super(context);
    bg = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
    new Timer();
}

@Override
public void onDraw(Canvas c) {
    Paint p = new Paint();
    if(!created) {
        w=getWidth();
        h=getHeight();
        p.setColor(Color.RED);
        p.setTextSize(40);
        bg = Bitmap.createScaledBitmap(bg, w, h, false);
        created = true;
    }
    if(created) {
        time++;
        c.drawBitmap(bg, 0,0,null);
        c.drawText(time+"", (int)(w/4),  (int)(h/4), p);
    }

}

class Timer extends Handler {
    private Timer() {
        handleMessage(obtainMessage(0));
    }

    @Override
    public void handleMessage(Message m) {
        invalidate();
        sendMessageDelayed(obtainMessage(0), 10);
    }
}

}

К вашему сведению, исходное изображение 300x225. Разрешение экрана моего планшета, до которого я масштабирую изображение, составляет 1280x800. Дело в том, что если я масштабирую фоновое изображение до sth, например (int)(.8*w), (int)(.8*h) или sth меньше или вообще не масштабирую изображение, то оно работает быстро, как и ожидалось.

Я пытался использовать ImageView и использовать setImageResource(R.drawable.my_image), но это было так же медленно. Я думал, что нарисовать изображение, соответствующее фону, должно быть очень просто для любого языка программирования, но у меня была эта проблема в течение очень долгого времени, даже после долгих поисков. Я надеюсь, что кто-нибудь может дать мне правильный ответ. Я был бы очень признателен за это.


person nick    schedule 02.02.2012    source источник


Ответы (1)


createScaledBitmap() не следует выполнять внутри вашей процедуры onDraw(). Он довольно медленный, поскольку использует процедуру усреднения пикселей для «сглаживания» растянутого растрового изображения. Создайте растянутое растровое изображение вне потока графического интерфейса, а затем просто нарисуйте его (canvas.drawBitmap) в методе onDraw(). Параметр фильтра можно использовать для создания масштабирования «ближайшего соседа», если установлено значение false. Это будет выглядеть «блочно», но обработка будет намного быстрее.

public static Bitmap createScaledBitmap
  (Bitmap src, int dstWidth, int dstHeight, boolean filter)
person BitBank    schedule 08.02.2012
comment
Я вызываю createScaledBitmap() в onDraw(), потому что именно тогда я могу получить ширину и высоту представления. И я вызываю его только один раз, используя if(!created), затем вызываю, затем устанавливаю created = true, а затем никогда больше не вызываю createScaledBitmap(). Так что это не плохо. Тем не менее, я все еще пытался вызвать его в конструкторе, но без разницы. - person nick; 11.02.2012