Sto utilizzando la funzione matrix.setPolyToPoly per trasformare una regione selezionata (4 angoli) di una bitmap in un rettangolo e normalmente funziona in modo sorprendente. Ma nel prossimo esempio:In alcuni casi la distorsione di un'immagine in un quadrilatero non funziona su Android
La funzione polyToPoly fallisce la prospettiva trasformano:
ho disegnato due linee per i test, le linee di Mark dove voglio i quattro punti selezionati .
Cosa sto facendo male? Grazie!
EDIT: Ho risolto il problema utilizzando canvas.drawBitmapMesh, grazie pskink per il vostro consiglio !!
Questo è il codice finale
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;
}
non si può fare tutto con 'setPolyToPoly', provare' Canvas.drawBitmapMesh' invece – pskink
Grazie! Ho aggiornato la domanda con il codice finale. –
@PepSantacruz Grazie per una domanda chiara e ben espressa. Lo spirito di SO è che domande e risposte possono essere utili agli altri molto tempo dopo il post originale. È questo lo spirito, potresti ripristinare la modifica alla tua domanda in modo che il codice sia quello del post originale (con il codice funzionante nella risposta come hai fatto tu)? Inoltre, potresti "accettare" la tua risposta. Facendo queste cose, i futuri visitatori saranno in grado di vedere una chiara differenza tra il codice che ha avuto un problema e il codice che ha risolto il problema. 'Accetta' farà un'indicazione evidente che questa risposta ha risolto il problema. – Gary99