开发者

How to convert coordinates of the image view to the coordinates of the bitmap?

In my app I need 开发者_如何学编程to let users to check the eyes at some photo. In OnTouchListener.onTouch(...) I get the coordinates of the ImageView.

How can I convert this coordinates to the point at the bitmap that was touched?


this works for me at least with API 10+:

final float[] getPointerCoords(ImageView view, MotionEvent e)
{
    final int index = e.getActionIndex();
    final float[] coords = new float[] { e.getX(index), e.getY(index) };
    Matrix matrix = new Matrix();
    view.getImageMatrix().invert(matrix);
    matrix.postTranslate(view.getScrollX(), view.getScrollY());
    matrix.mapPoints(coords);
    return coords;
}


Okay, so I've not tried this, but giving it a bit of thought, here's what I've got as a suggestion:

ImageView imageView = (ImageView)findViewById(R.id.imageview);
Drawable drawable = imageView.getDrawable();
Rect imageBounds = drawable.getBounds();

//original height and width of the bitmap
int intrinsicHeight = drawable.getIntrinsicHeight();
int intrinsicWidth = drawable.getIntrinsicWidth();

//height and width of the visible (scaled) image
int scaledHeight = imageBounds.height();
int scaledWidth = imageBounds.width();

//Find the ratio of the original image to the scaled image
//Should normally be equal unless a disproportionate scaling
//(e.g. fitXY) is used.
float heightRatio = intrinsicHeight / scaledHeight;
float widthRatio = intrinsicWidth / scaledWidth;

//do whatever magic to get your touch point
//MotionEvent event;

//get the distance from the left and top of the image bounds
int scaledImageOffsetX = event.getX() - imageBounds.left;
int scaledImageOffsetY = event.getY() - imageBounds.top;

//scale these distances according to the ratio of your scaling
//For example, if the original image is 1.5x the size of the scaled
//image, and your offset is (10, 20), your original image offset
//values should be (15, 30). 
int originalImageOffsetX = scaledImageOffsetX * widthRatio;
int originalImageOffsetY = scaledImageOffsetY * heightRatio;

Give this idea a try and see if it works for you.


besides considering the offset due to padding (margin is part of the layout, it's space outside the view and doesn't have to be considered), if the image is scaled you can get the image matrix (ImageView.getImageMatrix()) to scale coordinates.

EDIT: You can get x/y scaling factor and translation amount getting the values array and using respective index constants:

float[] values;
matrix.getValues(values);

float xScale = values[Matrix.MSCALE_X];

note that translation doesn't include padding, you still would have to consider that separately. translation is used for instance in FIT_CENTER scaling when there's some "blank" space.


I'd say you probably need to offset the coordinates from the ImageView with any padding or margins in the layout to get the correct coordinates of the BitMap.


To add to kcoppock's answer, I just want to add that:

//original height and width of the bitmap
int intrinsicHeight = drawable.getIntrinsicHeight();
int intrinsicWidth = drawable.getIntrinsicWidth();

may return an answer you're not expecting. These values depend on the dpi of the drawable folder you load the image from. For instance, you might get a different value if you load the image from /drawable vs /drawable-hdpi vs /drawable-ldpi.


Get floor Width and height

float floorWidth = floorImage.getWidth();
float floorHeight = floorImage.getHeight();

Calculate protionate value

float proportionateWidth = bitmapWidth / floorWidth;
float proportionateHeight = bitmapHeight / floorHeight;

Your X & Y

float x = 315;
float y = 119;

Multiple with PropotionateValue

x = x * proportionateWidth;
y = y * proportionateHeight;


As I came accross this question and tried it out myself, here is my solution. It seems to work with stretched and centered images.

class MyEditableImageView(context: Context, attrs: AttributeSet) :
    androidx.appcompat.widget.AppCompatImageView(context, attrs) {

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val image = drawable.toBitmap().copy(Bitmap.Config.ARGB_8888, true)
        val xp = (event.x - imageMatrix.values()[Matrix.MTRANS_X]) / imageMatrix.values()[Matrix.MSCALE_X]
        val yp = (event.y - imageMatrix.values()[Matrix.MTRANS_Y]) / imageMatrix.values()[Matrix.MSCALE_Y]
        if (xp >= 0 && xp < image.width && yp >= 0 && yp < image.height) {
            doSomethingOnImage(image, xp, yp)
            setImageBitmap(image)
        }
        return super.onTouchEvent(event)
    }

    ...

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜