Матрица просмотра изображений Android масштаб + перевод - PullRequest
30 голосов
/ 20 мая 2011

Я пытаюсь вручную получить изображение внутри изображения по центру и подгонять к экрану. Мне нужно сделать это с матрицей (позже я буду динамически менять матричное преобразование).

Проблема в том, что я не могу выровнять изображение по центру изображения (соответствующий масштаб). Вот код:

// Compute the scale to choose (this works)
float scaleX = (float) displayWidth / (float) imageWidth;
float scaleY = (float) displayHeight / (float) imageHeight;
float minScale = Math.min(scaleX, scaleY);

// tx, ty should be the translation to take the image back to the screen center
float tx = Math.max(0, 
        0.5f * ((float) displayWidth - (minScale * imageWidth)));
float ty = Math.max(0, 
        0.5f * ((float) displayHeight - (minScale * imageHeight)));

// Compute the matrix
Matrix m = new Matrix();
m.reset();

// Middle of the image should be the scale pivot
m.postScale(minScale, imageWidth/2, imageHeight/2);

// Translate
m.postTranslate(tx, ty);

imageView.setImageMatrix(m);

Приведенный выше код работает, если я не центрирую масштаб по центру изображения (но мне нужно будет сделать это позже, поэтому мне нужно выяснить формулу сейчас).

Я думал, что выполнение следующих действий решит проблему, но изображение все еще смещено (по направлению вниз и вправо).

tx += 0.5*imageWidth*minScale;
ty += 0.5*imageHeight*minScale;

Некоторые значения у меня есть: - изображение: 200x133 - дисплей: 800x480 - minScale: 2,4 - последний левый верхний угол изображения: 100, 67 (должно быть 17, 0)

Ответы [ 4 ]

66 голосов
/ 30 мая 2011

Существует удобный метод, называемый Matrix.setRectToRect (RectF, RectF, ScaleToFit) , чтобы помочь вам здесь.

Matrix m = imageView.getImageMatrix();
RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight);
RectF viewRect = new RectF(0, 0, imageView.getWidth(), imageView.getHeight());
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
imageView.setImageMatrix(m);

Это должно установить матрицу m, чтобы иметь комбинацию измасштабирование и преобразование значений, необходимых для отображения отрисованного по центру и размещения в виджете ImageView.

5 голосов
/ 30 мая 2011

Вот как я решил свою проблему, используя матрицы (запрошенные joakime в другом ответе):

private void setImageTransformation(float tx, float ty, float scale) {
    savedMatrix.reset();
    savedMatrix.postTranslate(-imageWidth / 2f, -imageHeight / 2f);
    savedMatrix.postScale(scale, scale);
    savedMatrix.postTranslate(tx, ty);
    imageView.setImageMatrix(savedMatrix);
}

public void resetImageMatrix() {
    if (!isImageLoaded()) return;

    imageWidth = imageView.getDrawable().getIntrinsicWidth();
    imageHeight = imageView.getDrawable().getIntrinsicHeight();

    float scaleX = (float) displayWidth / (float) imageWidth;
    float scaleY = (float) displayHeight / (float) imageHeight;
    minScale = Math.min(scaleX, scaleY);
    maxScale = 2.5f * minScale;

    initialTranslation.set(
              Math.max(0, 
                minScale * imageWidth / 2f 
                + 0.5f * (displayWidth - (minScale * imageWidth))), 
              Math.max(0, 
                minScale * imageHeight / 2f
                + 0.5f * (displayHeight - (minScale * imageHeight))));

    currentScale = minScale;
    currentTranslation.set(initialTranslation);
    initialImageRect.set(0, 0, imageWidth, imageHeight);

    setImageTransformation(initialTranslation.x, initialTranslation.y, 
                minScale);
}

Я немного обманываю, потому что щепотка на самом деле не центрирована между пальцами пользователя, чтоприемлемо в моем случае.

1 голос
/ 12 января 2017

Или используя

    m.postScale(minScale, minScale); //keep aspect ratio

    float tx = (getWidth() - bitmap1.getWidth()* scale) * 0.5f ;
    float ty = (getHeight() - bitmap1.getHeight()* scale) * 0.5f ;

    matrix.postTranslate(tx, ty );

где getWidth - ширина вашего изображения. У меня отлично работает

1 голос
/ 21 июля 2012

Эй, у меня была такая же проблема, а вы были так близко! Это был вопрос порядка операций, по крайней мере, для меня. У меня сработало следующее:

tx = (width - imgWidth) * 0.5f * scale;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...