I'm using matrix.setPolyToPoly function to transform a selected region (4 corners) of a bitmap into a rectangle and normally it works amazing. But in the next example:
The polyToPoly function fails the perspective transform:
I have drawn two lines for testing, the lines mark where I want the four selected points.
What I'm doing wrong? Thanks!
EDIT: I've solved the problem using canvas.drawBitmapMesh, Thanks pskink for your advice!!
This is the final code
private float[] generateVertices(int widthBitmap, int heightBitmap) {
float[] vertices=new float[(WIDTH_BLOCK+1)*(HEIGHT_BLOCK+1)*2];
float widthBlock = (float)widthBitmap/WIDTH_BLOCK;
float heightBlock = (float)heightBitmap/HEIGHT_BLOCK;
for(int i=0;i<=HEIGHT_BLOCK;i++)
for(int j=0;j<=WIDTH_BLOCK;j++) {
vertices[i * ((HEIGHT_BLOCK+1)*2) + (j*2)] = j * widthBlock;
vertices[i * ((HEIGHT_BLOCK+1)*2) + (j*2)+1] = i * heightBlock;
}
return vertices;
}
private Bitmap perspectiveTransformation(Bitmap bitmap, ArrayList<Point> bitmapPoints) {
Bitmap correctedBitmap;
int maxX = (int) Math.max(Math.abs(bitmapPoints.get(0).x - bitmapPoints.get(1).x), Math.abs(bitmapPoints.get(2).x - bitmapPoints.get(3).x));
int maxY = (int) Math.max(Math.abs(bitmapPoints.get(0).y - bitmapPoints.get(3).y), Math.abs(bitmapPoints.get(1).y - bitmapPoints.get(2).y));
Log.d("max", "x=" + maxX + " y=" + maxY); //This is the desired final size
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
correctedBitmap = Bitmap.createBitmap(maxX,maxY,conf); //the final bitmap
float mVertices[] =generateVertices(bitmap.getWidth(),bitmap.getHeight());
Point mLeftTop = bitmapPoints.get(0);
Point mRightTop = bitmapPoints.get(1);
Point mLeftBot = bitmapPoints.get(3);
Point mRightBot = bitmapPoints.get(2); //the points on the image where the user has clicked
Canvas canvas = new Canvas(correctedBitmap);
Matrix matrix = new Matrix();
matrix.setPolyToPoly(
new float[]{mLeftTop.x, mLeftTop.y,
mRightTop.x, mRightTop.y,
mRightBot.x, mRightBot.y,
mLeftBot.x, mLeftBot.y //the user's points
},
0,
new float[]{0, 0,
maxX - 1, 0,
maxX - 1, maxY - 1,
0, maxY - 1 //where I want the user points in the corrected image
}
, 0, 4);
canvas.concat(matrix);
Paint paint = new Paint();
paint.setAntiAlias(true); //testing parameters
paint.setFilterBitmap(true); //testing parameters
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
canvas.drawBitmapMesh(bitmap, WIDTH_BLOCK , HEIGHT_BLOCK, mVertices,0,null,0, paint); //draw the original bitmap into the corrected bitmap with PolyToPoly transformation matrix
canvas.drawLine(mLeftTop.x, mLeftTop.y, mRightBot.x, mRightBot.y, paint); //draw two lines for testing the transformation matrix
canvas.drawLine(mLeftBot.x, mLeftBot.y, mRightTop.x, mRightTop.y, paint);
//bitmap.recycle(); //just testing
return correctedBitmap;
}
Had the same issue with drawBitmap. Opened an issue in Skia - Android's Canvas backend
https://bugs.chromium.org/p/skia/issues/detail?id=8675#c4
private float[] generateVertices(int widthBitmap, int heightBitmap) {
float[] vertices=new float[(WIDTH_BLOCK+1)*(HEIGHT_BLOCK+1)*2];
float widthBlock = (float)widthBitmap/WIDTH_BLOCK;
float heightBlock = (float)heightBitmap/HEIGHT_BLOCK;
for(int i=0;i<=HEIGHT_BLOCK;i++)
for(int j=0;j<=WIDTH_BLOCK;j++) {
vertices[i * ((HEIGHT_BLOCK+1)*2) + (j*2)] = j * widthBlock;
vertices[i * ((HEIGHT_BLOCK+1)*2) + (j*2)+1] = i * heightBlock;
}
return vertices;
}
private Bitmap perspectiveTransformation(Bitmap bitmap, ArrayList<Point> bitmapPoints) {
Bitmap correctedBitmap;
int maxX = (int) Math.max(Math.abs(bitmapPoints.get(0).x - bitmapPoints.get(1).x), Math.abs(bitmapPoints.get(2).x - bitmapPoints.get(3).x));
int maxY = (int) Math.max(Math.abs(bitmapPoints.get(0).y - bitmapPoints.get(3).y), Math.abs(bitmapPoints.get(1).y - bitmapPoints.get(2).y));
Log.d("max", "x=" + maxX + " y=" + maxY); //This is the desired final size
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
correctedBitmap = Bitmap.createBitmap(maxX,maxY,conf); //the final bitmap
float mVertices[] =generateVertices(bitmap.getWidth(),bitmap.getHeight());
Point mLeftTop = bitmapPoints.get(0);
Point mRightTop = bitmapPoints.get(1);
Point mLeftBot = bitmapPoints.get(3);
Point mRightBot = bitmapPoints.get(2); //the points on the image where the user has clicked
Canvas canvas = new Canvas(correctedBitmap);
Matrix matrix = new Matrix();
matrix.setPolyToPoly(
new float[]{mLeftTop.x, mLeftTop.y,
mRightTop.x, mRightTop.y,
mRightBot.x, mRightBot.y,
mLeftBot.x, mLeftBot.y //the user's points
},
0,
new float[]{0, 0,
maxX - 1, 0,
maxX - 1, maxY - 1,
0, maxY - 1 //where I want the user points in the corrected image
}
, 0, 4);
canvas.concat(matrix);
Paint paint = new Paint();
paint.setAntiAlias(true); //testing parameters
paint.setFilterBitmap(true); //testing parameters
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
canvas.drawBitmapMesh(bitmap, WIDTH_BLOCK , HEIGHT_BLOCK, mVertices,0,null,0, paint); //draw the original bitmap into the corrected bitmap with PolyToPoly transformation matrix
canvas.drawLine(mLeftTop.x, mLeftTop.y, mRightBot.x, mRightBot.y, paint); //draw two lines for testing the transformation matrix
canvas.drawLine(mLeftBot.x, mLeftBot.y, mRightTop.x, mRightTop.y, paint);
//bitmap.recycle(); //just testing
return correctedBitmap;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With