2015-08-24 33 views
1

假设我有2个位图。一个是smallBitmap,另一个是largeBitmap。如何绘制位图到另一个位置,但进入给定的四边形(不需要矩形)?

我想将整个smallBitmap绘制成largeBitmap,但只绘制到bigBitmap的一部分,而不是以直线形式绘制,而是绘制成quadrilateral

我认为一个草图将最能说明我的意思:

enter image description here

这种情况的一个例子是倾斜的智能手机图像(如thisthis),你需要把截图到其屏幕。

输入是: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()); 
+0

请参阅Matrix.setPolyToPoly – pskink

回答

1

找到一个基于this post的答案。

似乎矩阵不能使用,因为它不能创建可能发生在三维世界中的梯形形状。

那么什么建议有使用“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); 

然而,中心裁剪,它仍然有这个问题,但如果你知道矩形的正确尺寸也得到了倾斜之前,你可以做之前裁剪,并将其作为输入。

至于文字,这是可以照常进行的,因为画布会与创建的矩阵保持一致。

+0

'“可悲的是,正如你所看到的,坐标没有被使用,所以你需要用数字来玩,直到你找到正确的数字,或者找到一个在坐标和所需值之间转换的公式。因为你使用了错误的API('Camera'),正确的API是'Matrix'和它的'setPolyToPoly'方法,它使用两个**精确**坐标数组:四维[x,y]可以看到'Camera' API返回'Matrix',与'setPolyToPoly'方法调用计算出的Matrix相同(如果它内部使用'setPolyToPoly'代码,我不会感到惊讶) – pskink

+0

@pskink如果您知道如何修复代码,请在新答案中写一个替代方案。这就是我发现的。 –

+0

参见http://stackoverflow.com/a/6106241/2252830 – pskink

0

偏斜位图,大概矩阵可以得心应手。

/*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); 
+0

我不知道倾斜和旋转值。只有其他位图的矩形的目标坐标。更新的问题,使其更清晰。 –

+0

由于您不需要缩放或旋转,因此您可以将旋转值用作零并将比例值作为(1,1)。尝试matrix.postSkew(float kx,float ky,float px,float py)其中px和py是转轴坐标。 – harshitpthk

+0

我不需要创建另一个位图。我写入largeBitmap。另外,px和py只有2个浮点数,而我有4个坐标。我应该怎么处理它们? –

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()); 
    } 
} 
+0

看起来像我已经尝试过的东西。哪些部分可以拉伸并进行中心作物伸展? –

+0

四边形真的只是为了边界?这将使小位图的转换完全不同!我会看看这个。 –

+0

我重写了我的答案,四边形现在用作边界区域来创建边界矩形。 –