How to Convert Coordinates of the Image View to the Coordinates of the Bitmap

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

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.

How to take real coordinates(X,Y) of Bitmap from imageView Android

use ImageView#getImageMatrix, something like this:

    final ImageView iv = new ImageView(this);
setContentView(iv);
// setup your image here by
// calling for example iv.setImageBitmap()
// or iv.setImageDrawable()
// or iv.setImageResource()
View.OnTouchListener otl = new View.OnTouchListener() {
Matrix inverse = new Matrix();
@Override
public boolean onTouch(View v, MotionEvent event) {
iv.getImageMatrix().invert(inverse);
float[] pts = {
event.getX(), event.getY()
};
inverse.mapPoints(pts);
Log.d(TAG, "onTouch x: " + Math.floor(pts[0]) + ", y: " + Math.floor(pts[1]));
return false;
}
};
iv.setOnTouchListener(otl);

Correspondence between ImageView coordinates and Bitmap Pixels - Android

Matteo,

It seems this is more a question of how much error you can (subjectively) tolerate in which pixels you send to the server. The fact remains that for any aspect ratio that does not come out to a nice neat integer, you have to decide which direction to 'push' your selection box.

The solutions you linked to are perfectly good solutions. You have to ask yourself: Will the user notice if the image I process is one pixel off from the selection box shown on the screen? My guess is probably not. I can't imagine the user will have that sort of pixel precision anyways when selecting a rectangle with their big fat finger on a touchscreen :D

Since this is the case, I would just let the floor()-ing that occurs when casting to an integer take care of which pixels you end up passing to the server.

Let's look at an example.

Let's define the width and height of our ImageView and Bitmap to be:

ImageViewWidth = 400, ImageViewHeight = 150
BitmapWidth = 176, BitmapHeight = 65

Then the aspect ratios you will use to convert your selection box between them will be:

WidthRatio = BitmapWidth / ImageViewWidth = 175 / 400 = 0.44
HeightRatio = BitmapHeight / ImageViewHeight = 65 / 150 = 0.44

Some nice ugly numbers. Whatever pixel I am on in the ImageView will correspond to a pixel in the Bitmap like so:

BitmapPixelX = ImageViewPixelX * WidthRatio
BitmapPixelY = ImageViewPixelY * HeightRatio

Now, I put this Bitmap on the screen in my ImageView for the user to select a rectangle, and the user selects a rectangle with top-left and bottom-right coordinates in the ImageView as such:

RectTopLeftX = 271, RectTopLeftY = 19
RectBottomRightX = 313, RectBottomRightY = 42

How do I determine which pixels in the Bitmap these correspond to? Easy. The ratios we determined earlier. Let's look at just the top-left coordinates for now.

RectTopLeftX * WidthRatio = 271 * .44 = 119.24
RectTopLeftY * HeightRatio = 19 * .44 = 8.36

For RectTopLeftX, we find ourselves at a BitmapPixelX value of 119, and then about a quarter of a way into the pixel. Well, if we floor() this value and the corresponding BitmapPixelY value of 8.36, we will be sending pixel (119, 8) to the server for processing. If we were to ceil() these values, we will be sending pixel (120, 9) to the server for processing. This is the part that is entirely up to you.

You will (nearly) always land in some fractional part of a pixel. Whether you send the pixel you land in, or the one next to it is your call. I would say that this is going to be entirely unnoticeable by your user, and so to reiterate, just let the floor()-ing that occurs when casting to an integer take care of it.

Hope that helps!

[EDIT]

Upon reading the question again more slowly, I think I better understand what you are asking/confused about. I will use my example above to illustrate.

You are saying that there are 176 pixels in the Bitmap, and 400 pixels in the ImageView. Therefore, the mapping from one to the other is not 1:1, and this will cause problems when figuring out what pixels to pull out for processing.

But it doesn't! When you convert the coordinates of the rectangle bounds in the ImageView to coordinates in the Bitmap, you're simply giving the range of pixels to iterate over in the Bitmap. It's not a description of how each individual pixel in the ImageView maps to a corresponding pixel in the Bitmap.

I hope that clears up my confusion about your confusion.

Convert View Rect coordinates to bitmap area

So the solution was to scale the bitmap to screens size.

Bitmap bitmap = BitmapUtil.scaleBitmap(bitmap, screenWidth, screenHeight);

Then crop by the Rect cordinates

Bitmap cropBitmap = Bitmap.createBitmap(bitmap, rect.left, rect.top, rect.width(), rect.height());

Transform Bitmap or ImageView at specific coordinates

You can try creating second mutable bitmap like this

Bitmap originalBitmap;
Bitmap b = Bitmap.createBitmap(originalBitmap.getWidth(), originalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b)

Then you can draw original bitmap on top of new bitmap applying transformations. See Canvas API for more details.

For example use the following method:

c.drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)

Update

Regarding use of Matrix, it's just a guess, you can try method mapPoints(float[] src, float[] dest). I also did a quick search on Google and found web page with examples. Have a look.

Update 2

Dardan was able to achieve his goal with the following method:

drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, Paint paint);

Method description:

Draw the bitmap through the mesh, where mesh vertices are evenly
distributed across the bitmap. There are meshWidth+1 vertices across,
and meshHeight+1 vertices down. The verts array is accessed in
row-major order, so that the first meshWidth+1 vertices are
distributed across the top of the bitmap from left to right. A more
general version of this method is drawVertices().

Get coordinates of a Bitmap image from an ImageView twice as small

I haven't found an actual way to do this. Here's the method I've used:

Upon creating the ImageView, scroll to a known location.

int ivX = 0;
int ivY = 0;

_iv.invalidate();
_iv.scrollTo(ivX, ivY);

This way I have the exact (x, y) coordinates of where I am. Then, I've implemented the onScroll() method and used the generated distances to recalculate my (x, y) coordinates:

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//Add the scroll distance to the old X, Y coordinates
ivX += distanceX;
ivY += distanceY;

//Scroll to the new location
_iv.scrollTo(ivX, ivY);

return false;
} //End onScroll()

In addition, to get a better understanding of how scrollTo() works and the relationship between the coordinates of the image and its container, follow this link to a different post of mine.



Related Topics



Leave a reply



Submit