0

I am trying to make an app where you can place points/markers on an image using an imageview. What I am trying to do is get the coordinates of a touch event and then drawing a marker bitmap at those coordinates, however MotionEvent.getX() and MotionEvent.getY() return values that are strangely shifted. When I click the imageView, the markers appear shifted down and left. I have tried using MotionEvent.getRawX() and MotionEvent.getRawY(), however these seem to make the shifting become worse. Here is an example: Image of shifted points

Here is the current code:

        ImageView mapImage = findViewById(R.id.mapImageView);
        Bitmap imageBitmap = BitmapFactory.decodeFile(projectfile2.getPath()).copy(Bitmap.Config.ARGB_8888,true);
        mapImage.setImageBitmap(imageBitmap);
        Canvas canvas = new Canvas(imageBitmap);
        //canvas.setBitmap(imageBitmap);
        //canvas.drawBitmap(imageBitmap,0,0,null);
        Bitmap pinBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.red_marker);
        mapImage.setOnTouchListener((view, motionEvent) -> {
            ImageView view2 = (ImageView) view;
            //view2.bringToFront();
            viewTransformation(view2, motionEvent);
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                float x = motionEvent.getX();
                float y = motionEvent.getY();
                canvas.drawBitmap(pinBitmap,x,y,null);
                Log.d("app123_X_and_Y",x+" | "+y);
            }
            return true;
        });

XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".IndoorMapView">

    <ImageView
        android:id="@+id/mapImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/rectangle"
        tools:srcCompat="@tools:sample/avatars"
        android:contentDescription="Map" />
</RelativeLayout>

Any ideas on how to get the correct coordinates? One quick theory I have is that when I set the canvas bitmap, its not setting it to the same size, however I'm not sure if that's how canvas' work. Thank you.

Phantom37
  • 21
  • 8
  • How did you create the `imageView` (show your xml)? most likely the image view is scaling the image down to fit the screen, thus the coordinates are off by the scale factor. – Andrew Jul 06 '23 at 14:35
  • My apologies, I added the XML to the post. I currently have it to wrap_content, however switching it to match_parent gives the same result. – Phantom37 Jul 06 '23 at 16:30
  • Thanks xml was to see if you had set any of the scaling stuff, but it still might be scaling it. Try something like `Matrix imgMatrix = mapImage.getImageMatrix()` then try `dump` or `toString` on that to get values of the Matrix being applied to the image. Or try `imgMatrix.isIdentity()` to see if it returns false. – Andrew Jul 06 '23 at 17:21
  • `mapImage.getImageMatrix().toString()` returns this: `Matrix{[0.8178694, 0.0, 0.0][0.0, 0.8178694, 69.391754][0.0, 0.0, 1.0]}` and `mapImage.getImageMatrix().toString` returns `false`. Can you help me decipher the first one because I would like to know what it means. Thanks! – Phantom37 Jul 06 '23 at 18:21

1 Answers1

0

So the imageView is being scaled down and translated in the Y direction based on matrix used.

This post gives some explanation of Matrix's used with view

Another article to explain the matrix

From memory of doing something similar a while ago you need to invert the matrix as you want to find the coordinates on the imageView that match the point you clicked (so they need to be scaled up)

Then map your points

e.g. something like this should work (not tested but I do something similar in my app to handle clicks on a scaled view)

// Create a new matrix to hold the inverted matrix
Matrix mappingMatrix = new Matrix();
// Create a copy of the imageView matrix but inverted
imgMatrix.invert(mappingMatrix);
// map your input points to where they should appear on the imageView
// x and y in a float array as that how mapPoints takes input
float[] points = new float[2];
points[0] = motionEvent.getX();
points[1] = motionEvent.getY();
mappingMatrix.mapPoints(points);
float x = points[0];
float y = points[1];

mapPoints reference

Andrew
  • 8,198
  • 2
  • 15
  • 35
  • Thank you, it worked slightly better, however the points are still shifted by a considerable amount. It gets increasingly worse when you use a horizontal image. – Phantom37 Jul 07 '23 at 14:06