1

2 つのビットマップがあるとします。1 つは smallBitmap で、もう 1 つは largeBitmap です。

smallBitmap 全体を largeBitmap に描画したいのですが、largeBitmap の一部にのみ描画し、直線の四角形ではなく四角形に描画したいと考えています。

私が言いたいことは、スケッチが最もよく説明できると思います。

ここに画像の説明を入力

このシナリオの例は、スクリーンショットを画面に配置する必要がある傾斜したスマートフォンの画像 (これまたはこのなど) です。

入力は、smallBitmap、largeBitmap、largeBitmap の「四角形」座標 (smallBitmap を配置する場所) です。

largeBitmap の「四角形」には 4 つの座標があり、四角形である必要はありません。たとえば、平行四辺形や台形などです。

smallBitmap を largeBitmap 内の四角形にスケーリングする必要があります。また、センター クロップ スケーリングをサポートして、歪まないようにする必要があります。

テキストを同じように扱う方法も知る必要がありますが、ほぼ同じ解決策だと思います。


これは私が試したものですが、スケーリングさえしません:

    //mBigBitmap: size is 720x1280
    //mSmallBitmap: size is 720x720
    mLeftTop = new Point(370, 358);
    mRightTop = new Point(650, 384);
    mLeftBot = new Point(375, 972);
    mRightBot = new Point(660, 942);
    Canvas canvas = new Canvas(mBigBitmap);
    final Matrix matrix = new Matrix();
    matrix.setPolyToPoly(new float[]{0, 0,
                    mBigBitmap.getWidth() - 1, 0,
                    0, mBigBitmap.getHeight() - 1,
                    mBigBitmap.getWidth() - 1, mBigBitmap.getHeight() - 1},
            0,
            new float[]{mLeftTop.x, mLeftTop.y,
                    mRightTop.x, mRightTop.y,
                    mLeftBot.x, mLeftBot.y,
                    mRightBot.x, mRightBot.y
            }
            , 0, 4);
    canvas.drawBitmap(mSmallBitmap, matrix, new Paint());
4

3 に答える 3

1

この投稿に基づいて回答が見つかりました。

Matrix は、3D の世界で発生する可能性のある台形を作成できないため、使用できないようです。

したがって、次のように「 Camera」クラスを使用することが提案されています。

    Canvas canvas = new Canvas(bigBitmap);
    Matrix matrix = new Matrix();
    Camera camera = new Camera();
    camera.save();
    camera.translate(...,...,0);
    camera.rotateX(...);
    camera.rotateY(...);
    camera.rotateZ(...);
    camera.getMatrix(matrix);
    int centerX = bigBitmap.getWidth() / 2;
    int centerY = bigBitmap.getHeight() / 2;
    matrix.preTranslate(-centerX, -centerY); //This is the key to getting the correct viewing perspective
    matrix.postTranslate(centerX, centerY);
    canvas.concat(matrix);
    camera.restore();
    canvas.drawBitmap(mSmallBitmap, matrix, new Paint());

悲しいことに、ご覧のとおり、座標は使用されていないため、正しくなるまで数字をいじるか、座標と必要な値の間で変換する式を見つける必要があります。

元の質問の要件を完全に満たしていないため (座標が使用されていないため)、この回答を正しいものとしてマークしません。

さらに、このソリューションの使用中にテキストを処理する方法が見つかりません。

ただし、機能するため、他の人にとっては役立つかもしれません。


編集: setPolyToPoly が画像をまったくスケーリングしない理由は、最初の入力配列が正しくないためと思われます: 小さなビットマップではなく、大きなビットマップのサイズとして設定されました。

したがって、これは正しいコードです。

mLeftTop = new Point(370, 358);
mRightTop = new Point(650, 384);
mLeftBot = new Point(375, 972);
mRightBot = new Point(660, 942);
Canvas canvas = new Canvas(mBigBitmap);
final Matrix matrix = new Matrix();
matrix.setPolyToPoly(new float[]{0, 0,
                mSmallBitmap.getWidth() - 1, 0,
                0, mSmallBitmap.getHeight() - 1,
                mSmallBitmap.getWidth() - 1, mSmallBitmap.getHeight() - 1},
        0,
        new float[]{mLeftTop.x, mLeftTop.y,
                mRightTop.x, mRightTop.y,
                mLeftBot.x, mLeftBot.y,
                mRightBot.x, mRightBot.y
        }
        , 0, 4);
canvas.concat(matrix);
final Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(mSmallBitmap, 0, 0, paint);

ただし、中央トリミングの場合、この問題はまだありますが、傾斜する前に長方形の正しいサイズがわかっている場合は、前にトリミングを行い、それを入力として設定できます。

テキストに関しては、キャンバスは作成されたマトリックスにとどまるため、これは通常どおり可能です。

于 2015-08-25T09:24:55.133 に答える
0

ビットマップを歪めるには、おそらく Matrix が便利です。

   /*use values accordingly*/
   Matrix matrix = new Matrix();
   matrix.postScale(curScale, curScale);  
   matrix.postRotate(curRotate);
   matrix.postSkew(curSkewX, curSkewY);

   Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bmpWidth, bmpHeight, matrix, true);
   myImageView.setImageBitmap(resizedBitmap);
于 2015-08-24T11:04:05.220 に答える
0

私の答えでは、小さいBitmapものを大きいものBitmapに描き、それをSurfaceView.

  1. 境界四角形を使用して、境界四角形を作成します。
  2. 外接する四角形を使用して変換を作成するMatrix
  3. Matrix.ScaleToFit.CENTER小さいBitmap. _

これらの手順を実行したら、大きいBitmap方が使用しているキャンバスに描画します。境界の四角形は赤で、境界の四角形は青で、大きいBitmap方は緑で描かれています。小さい方Bitmapを青Bitmap(外接する四角形) に置き換えます。

public class MainActivity extends Activity {
final String TAG = this.getClass().getName();

SurfaceView surfaceView;
Bitmap bitmap;
Bitmap bigBitmap;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
    surfaceView.getHolder().addCallback(new SurfaceHolder.Callback2() {
        @Override
        public void surfaceRedrawNeeded(SurfaceHolder holder) {

        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            Canvas surfaceCanvas = holder.lockCanvas();

            surfaceCanvas.drawBitmap(bigBitmap, 0, 0, new Paint());

            holder.unlockCanvasAndPost(surfaceCanvas);
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }
    });

    bitmap = Bitmap.createBitmap(64, 192, Bitmap.Config.ARGB_8888);
    {
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        canvas.drawRect(0, 0, 64, 192, paint);
    }

    bigBitmap = Bitmap.createBitmap(768,768, Bitmap.Config.ARGB_8888);
    {
        Canvas canvas = new Canvas(bigBitmap);

        // Fill background - For visual reference
        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        canvas.drawRect(0, 0, bigBitmap.getWidth(), bigBitmap.getHeight(), paint);

        // Setup transformation
        Matrix matrixPoly = new Matrix();
        Log.i(TAG, "matrixPoly: " + matrixPoly);

        // Draw Quadrilateral - For visual reference
        boolean canScale;
        canScale = matrixPoly.setPolyToPoly(new float[]{0,0, 64,0, 0,192, 64,192},
                0,
                new float[]{32,32, 96,16, 16,300, 128,256},
                0,
                4);

        Log.i(TAG, "matrixPoly: " + matrixPoly);
        Log.i(TAG, "matrixPoly canScale: " + canScale);

        canvas.drawBitmap(bitmap, matrixPoly, new Paint());

        // Points of Quadrilateral
        // {32,32, 96,16, 16,300, 128,256}
        float rectInQLeft = Math.max(32, 16);
        float rectInQTop = Math.min(32, 16);
        float rectInQRight = Math.min(96, 128);
        float rectInQBottom = Math.max(300, 256);
        ;
        Matrix matrixRect = new Matrix();
        Log.i(TAG, "matrixRect: " + matrixRect);
        canScale = matrixRect.setRectToRect(new RectF(0, 0, 64, 192),
                new RectF(rectInQLeft, rectInQTop, rectInQRight, rectInQBottom),
                Matrix.ScaleToFit.CENTER);

        Log.i(TAG, "matrixRect: " + matrixRect);
        Log.i(TAG, "matrixRect canScale: " + canScale);

        // Draw scaled bitmap
        Canvas smallBitmapCanvas = new Canvas(bitmap);
        Paint smallBitmapPaint = new Paint();
        smallBitmapPaint.setColor(Color.BLUE);
        smallBitmapCanvas.drawRect(0, 0, 64, 192, smallBitmapPaint);

        canvas.drawBitmap(bitmap, matrixRect, new Paint());
    }
}
于 2015-08-25T21:53:03.600 に答える