LINUX.ORG.RU

Как корректно масштабировать картинку в Андроид при перерисовке

 anroid


0

1

Имеется картинка (bitmap) определённого размера, но мне надо её вывести на другой размер (отмасштабировать). Я делаю так:

b = Bitmap.createScaledBitmap(bitmap, width, height, true);
        

canvas.drawBitmap(b, 0, 0, drawPaint);

Это код мне студия подчёркивает и говорит следующее :

Avoid object allocations during draw/layout operations (preallocate and reuse instead) Inspection info:You should avoid allocating objects during a drawing or layout operation. These are called frequently, so a smooth UI can be interrupted by garbage collection pauses caused by the object allocations.

И похоже, правильно говорит. Действительно, похоже, время от времени врубается сборщик мусора и подтормаживает процесс отрисовки.

Но что делать - нигде не написано! Весь интернет говорит createScaledBitmap. А как делать это правильно?

Нужно из картинки одного размера получить картинку другого размера, без new.

★★★★

Последнее исправление: lenin386 (всего исправлений: 3)

Звучит как проблема которая не относится к Java/Android.

protected Bitmap b = null;

void draw() {
  if (b == null) b = Bitmap.createScaledBitmap(bitmap, width, height, true);

  drawBitmap(b);

  if (resizeFlag) b = null;
}

И учитывая что это какой нибудь OpenGL, ты можешь менять положение точек полигонов на котором рисуется твоя текстура, а не сам Bitmap. См drawBitmapMesh.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 6)
Ответ на: комментарий от MOPKOBKA

Она в таком случае не будет обновляться, при обновление исходного bitmap. Исходный bitmap постоянно обновляется. А b (scaled) - остаётся такой же. Это не то, что надо.

lenin386 ★★★★
() автор топика
Последнее исправление: lenin386 (всего исправлений: 3)
Ответ на: комментарий от lenin386

Знаю, когда обновляется. Каждый цикл перерисовки.

Не знаешь. Это только твое предположение.

В общем, решение архитектурное - ты избавляешься от прямых изменений атрибутов объекта, то есть нигде не пишешь чтоТоТам.bitmap = myNewFullSizeBitmap, а используешь модель publisher/subscriber, в котором рассылаешь уведомление об изменении битмапа всем заинтересованным, а они там уже у себя создают отскалированные битмапы, логгируют, пишут в файлы - в общем, творят что хотят. При этом вся эта активность уезжает из момента прорисовки в момент обновления битмапа (а еще плюсом ты получаешь отсутствие жесткой связки владельца битмапа и потребителя, что скорей положительно)

Вариант два - создаешь BitmapScaler у которого есть метод getScaledBitmap(origin, x, y) и который создает новый отскалированный битмап если старые и новые аргументы не совпадают. А если совпадают - то возвращает ранее вычисленый. Типа такого

class BitmapScaler {

    private Bitmap src;
    private int width;
    private int height;

    private Bitmap scaled;

    public BitmapScaler() { src = null; width = -1; height = -1; }
    public Bitmap getScaledBitmap(Bitmap newsrc, int w, int h) {
        if ((w != this. width) ||
            (h != this. height) ||
            ((this.src == null) || (!this.src.sameAs(newsrc))
        ) {
            this.scaled = Bitmap.createScaledBitmap(newsrc, w, h);
            this.width = w;
            this.height = h;
            this.src = newsrc;
        }
        return this.scaled;
    }
}

…

canvas.drawBitmap(scaler.getScaledBitmap(bitmap, width, height), …);

Это избавит тебя от постоянных пересозданий битмапа.

no-dashi-v2 ★★★
()

Нужно из картинки одного размера получить картинку другого размера, без new.

Тогда тебе не в Bitmap, потому что Bitmap как правило immutable. Единственный вариант его поменять - использовать setPixels(). И самому написать масштабирование на основе данных взятых из оригинала через getPixels.

Ну или напрямую рисовать скалированный битмап через Canvas.drawBitmap(Bitmap, Rect, Rect, Paint)

no-dashi-v2 ★★★
()
Ответ на: комментарий от no-dashi-v2

Ну или напрямую рисовать скалированный битмап через Canvas.drawBitmap(Bitmap, Rect, Rect, Paint)

Хех, спасибо. Именно это мне и надо было. Я ж только вкатываюсь :-)

lenin386 ★★★★
() автор топика
Последнее исправление: lenin386 (всего исправлений: 1)