Правильные преобразования для масштабирования изображения
Вопрос
Я пишу приложение для Android (хотя я думаю, что это общий вопрос), и мне нужно отобразить большое изображение (в ImageView), которое можно прокручивать и масштабировать.Мне удалось заставить работать прокрутку, фиксируя события касания и выполняя матричные переводы, и сейчас я работаю над масштабированием.
Если я просто применю преобразование масштаба к изображению, оно увеличится в исходной точке, то есть в верхнем левом углу экрана.Я хотел бы увеличить масштаб в центре экрана.Судя по тому, что я прочитал, это означает, что мне нужно преобразование, чтобы сделать начало координат центром экрана.Я думаю, что требуется что-то вроде следующего: для простоты предположим, что центр экрана равен (5, 5)...
-Translate by (-5, -5)
-Scale by the zoom factor
-Translate by (+5, +5)*zoomfactor
К сожалению, похоже, это не работает — кажется, что зум перемещается куда угодно, НО в центр… может кто-нибудь мне здесь помочь?
РЕДАКТИРОВАТЬ:Это код, который теперь работает
Matrix zoommatrix = new Matrix();
float[] centerpoint = {targetimageview.getWidth()/2.0f, targetimageview.getHeight()/2.0f};
zoommatrix.postScale(zoomfactor, zoomfactor, centerpoint[0], centerpoint[1]);
zoommatrix.preConcat(targetimageview.getImageMatrix());
targetimageview.setImageMatrix(zoommatrix);
targetimageview.invalidate();
Решение
Проверьте ImageViewTouchBase в приложении «Камера» исходного кода Android;его метод "zoomTo" делает это:
protected void zoomTo(float scale, float centerX, float centerY) {
if (scale > mMaxZoom) {
scale = mMaxZoom;
}
float oldScale = getScale();
float deltaScale = scale / oldScale;
mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY);
setImageMatrix(getImageViewMatrix());
center(true, true);
}
Этот центральный метод, вероятно, вам действительно будет интересен:
protected void center(boolean horizontal, boolean vertical) {
if (mBitmapDisplayed.getBitmap() == null) {
return;
}
Matrix m = getImageViewMatrix();
RectF rect = new RectF(0, 0,
mBitmapDisplayed.getBitmap().getWidth(),
mBitmapDisplayed.getBitmap().getHeight());
m.mapRect(rect);
float height = rect.height();
float width = rect.width();
float deltaX = 0, deltaY = 0;
if (vertical) {
int viewHeight = getHeight();
if (height < viewHeight) {
deltaY = (viewHeight - height) / 2 - rect.top;
} else if (rect.top > 0) {
deltaY = -rect.top;
} else if (rect.bottom < viewHeight) {
deltaY = getHeight() - rect.bottom;
}
}
if (horizontal) {
int viewWidth = getWidth();
if (width < viewWidth) {
deltaX = (viewWidth - width) / 2 - rect.left;
} else if (rect.left > 0) {
deltaX = -rect.left;
} else if (rect.right < viewWidth) {
deltaX = viewWidth - rect.right;
}
}
postTranslate(deltaX, deltaY);
setImageMatrix(getImageViewMatrix());
}