web-dev-qa-db-ja.com

Android画像ビューマトリックススケール+変換

画面の中央に合わせて画面に合わせて、imageview内の画像を手動で取得しようとしています。マトリックスを使用してそれを行う必要があります(後でマトリックス変換を動的に変更します)。

問題は、ビューの中央に画像を取得できないことです(スケールが適切です)。コードは次のとおりです。

// 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でなければなりません)

30

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ウィジェット内で中心に合わせてドローアブルを表示するために必要なスケーリングと変換のコンボを設定する必要があります。

66
Joakim Erdfelt

マトリックスを使用して問題を解決した方法は次のとおりです(他の回答の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);
}

ピンチが実際にはユーザーの指の中央にないため、ここで少し浮気しています。これは私の場合は許容範囲です。

5

または使用

    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はimageViewの幅です。私にぴったり

1
voytez

ちょっと私は同じ問題を抱えていた、とあなたはああとても近くにいた!少なくとも私にとっては、それは運用上の問題でした。次は私のために働いた:

tx = (width - imgWidth) * 0.5f * scale;
1
scone