Feat[cropper]: DO NOT USE. Implement generation of hi-res overlays on image sides/corners

This commit is contained in:
artdeell 2023-12-29 23:40:41 +03:00 committed by Maksim Belov
parent f84713e0ac
commit 8286d0a839

View File

@ -13,14 +13,46 @@ public class RegionDecoderCropBehaviour extends BitmapCropBehaviour {
private Bitmap mOverlayBitmap; private Bitmap mOverlayBitmap;
private final Rect mOverlayDst = new Rect(0, 0, 0, 0); private final Rect mOverlayDst = new Rect(0, 0, 0, 0);
private boolean mRequiresOverlayBitmap; private boolean mRequiresOverlayBitmap;
private boolean mRenderLowResBackground;
private final Matrix mDecoderPrescaleMatrix = new Matrix(); private final Matrix mDecoderPrescaleMatrix = new Matrix();
private final Handler mHiresLoadHandler = new Handler(); private final Handler mHiresLoadHandler = new Handler();
private final Runnable mHiresLoadRunnable = ()->{ private final Runnable mHiresLoadRunnable = ()->{
Rect subsectionRect = new Rect(0,0, mHostView.getWidth(), mHostView.getHeight()); Rect subsectionRect = new Rect(0,0, mHostView.getWidth(), mHostView.getHeight());
Rect decoderRect = new Rect(0, 0, mBitmapDecoder.getWidth(), mBitmapDecoder.getHeight()); Rect decoderRect = new Rect(0, 0, mBitmapDecoder.getWidth(), mBitmapDecoder.getHeight());
transformRectToDecoderCoords(subsectionRect); Rect subsectionIntersection = new Rect();
if(!decoderRect.contains(subsectionRect)) return; Matrix matrix = createDecoderImageMatrix();
mOverlayBitmap = mBitmapDecoder.decodeRegion(subsectionRect, null); Matrix inverse = new Matrix();
inverse(matrix, inverse);
transformRect(subsectionRect, inverse);
// If our current sub-section is bigger than the decoder rect, skip.
// We do this to avoid unnecerssarily loading the image at full resolution.
if(subsectionRect.width() > decoderRect.width()
|| subsectionRect.height() > decoderRect.height()) return;
// If our current sub-section doesn't even intersect the decoder rect, we won't even
// be able to create an overlay. So, skip.
if(!subsectionIntersection.setIntersect(decoderRect, subsectionRect)) return;
// In my testing, decoding a region smaller than that breaks the current region decoder instance.
// So, if it is smaller, skip.
if(subsectionIntersection.width() < 16 || subsectionRect.width() < 16) return;
mOverlayBitmap = mBitmapDecoder.decodeRegion(subsectionIntersection, null);
if(decoderRect.contains(subsectionRect)) {
// Doing the matrix approach when the subsection is fully contained within the
// decoder rect causes weird issues with width/height, so just force the full View
// width/height there
mOverlayDst.top = mOverlayDst.left = 0;
mOverlayDst.right = mHostView.getWidth();
mOverlayDst.bottom = mHostView.getHeight();
// DIsable the low-res rendering as the overlay completely fills the view.
mRenderLowResBackground = false;
} else {
// When not fully containing the image we still need a hi-res version, so transform the
// intersection back into View coordinate space to use as the destination.
// Sadly this causes weird issues with the resolution. Have no idea how to resolve yet.
transformRect(subsectionIntersection, matrix);
mOverlayDst.set(subsectionIntersection);
// Render the low-res original image in the background to avoid the messy corners.
mRenderLowResBackground = true;
}
mHostView.invalidate(); mHostView.invalidate();
}; };
@ -41,13 +73,8 @@ public class RegionDecoderCropBehaviour extends BitmapCropBehaviour {
@Override @Override
public void drawPreHighlight(Canvas canvas) { public void drawPreHighlight(Canvas canvas) {
if(mOverlayBitmap != null) { if(mOverlayBitmap == null || mRenderLowResBackground) super.drawPreHighlight(canvas);
mOverlayDst.right = mHostView.getWidth(); if(mOverlayBitmap != null) canvas.drawBitmap(mOverlayBitmap, null, mOverlayDst, null);
mOverlayDst.bottom = mHostView.getHeight();
canvas.drawBitmap(mOverlayBitmap, null, mOverlayDst, null);
}else {
super.drawPreHighlight(canvas);
}
} }
@Override @Override
@ -117,26 +144,22 @@ public class RegionDecoderCropBehaviour extends BitmapCropBehaviour {
} }
/** /**
* Create a Matrix that can be used to transform points from the View coordinate space to the * Create a Matrix that can be used to transform points from the bitmap coordinate space into the
* BitmapRegionDecoder coordinate space based on current pan and zoom transforms. * View coordinate space.
* @return the newly allocated Matrix for these operations
*/ */
private Matrix createDecoderImageInverse() { private Matrix createDecoderImageMatrix() {
Matrix decoderImageMatrix = new Matrix(mDecoderPrescaleMatrix); Matrix decoderImageMatrix = new Matrix(mDecoderPrescaleMatrix);
decoderImageMatrix.postConcat(mZoomMatrix); decoderImageMatrix.postConcat(mZoomMatrix);
decoderImageMatrix.postConcat(mTranslateMatrix); decoderImageMatrix.postConcat(mTranslateMatrix);
inverse(decoderImageMatrix, decoderImageMatrix);
return decoderImageMatrix; return decoderImageMatrix;
} }
/** /**
* Transform the coordinates of the Rect into the coordinate space of RegionImageDecoder * Transform the coordinates of the Rect using the supplied Matrix.
* based on currently applied pan/zoom transforms, and write them back into the current
* Rect.
* @param rect the input/ouput Rect for this operation * @param rect the input/ouput Rect for this operation
* @param regionImageInverse the Matrix for transforming the Rect.
*/ */
private void transformRectToDecoderCoords(Rect rect) { private void transformRect(Rect rect, Matrix regionImageInverse) {
Matrix regionImageInverse = createDecoderImageInverse();
float[] inOutDecodeRect = new float[8]; float[] inOutDecodeRect = new float[8];
inOutDecodeRect[0] = rect.left; inOutDecodeRect[0] = rect.left;
inOutDecodeRect[1] = rect.top; inOutDecodeRect[1] = rect.top;