Android get Position of Bitmap in ImageView - android

I am using CropView which extends an Android ImageView. It allows the image with in the the view to be scaled and moved around. there does not appear to be any public reference to the image position or scale. Is there a way to get the position of an image relative to a regular ImageView that I can try.
I have also tried setting a touch listener on the CropView that simply prints the x & y positions of the touch but i don see how i can use these to move get the updated position of the image.
mCropView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(TAG, "///" + event.getX() + " __ " + event.getY());
return false;
}
});

https://github.com/lyft/scissors/blob/master/scissors/src/main/java/com/lyft/android/scissors/CropView.java
The CropView itself is the viewport. Cropview has two methods getViewportWidth
and getViewportHeight. You'll need them.
The image that is scaled, moved, cropped etc is a Drawable. Drawable has a getBounds method that will return a Rect. You can get the top, left width and height from this Rect but you need to get the Drawable first.
CropView calls this Drawable "bitmap". You can get it calling the CropView's getImageBitmap() method.
Once you have it, call getBounds which gives you the image's Rect.
To get the x and y you want you'll have to do a bit of math with the Rect's top, left, width and height along with the viewport's height and width which you'll get from CropView's getViewportHeight and getViewportWidth methods.
Simply:
vpwidth=cropview.getViewPortWidth();
vpheight=cropview.getViewPortHeight();
imagetop=cropview.getImageBitmap().getBounds().top;
imageleft=cropview.getImageBitmap().getBounds().left;
imageheight=cropview.getImageBitmap().getBounds().height;
imagewidth=cropview.getImageBitmap().getBounds().width;
>math here

You could try out the method below,
final float[] getPointOfTouchedCordinate(ImageView view, MotionEvent e) {
final int index = e.getActionIndex();
final float[] coords = new float[] { e.getX(index), e.getY(index) };
Matrix m = new Matrix();
view.getImageMatrix().invert(m);
m.postTranslate(view.getScrollX(), view.getScrollY());
m.mapPoints(coords);
return coords;
}
you can get the value
mCropView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
float[] points = getPointOfTouchedCordinate(v, event);
Log.d(TAG, "///" + points[0] + " __ " + points(1));
return false;
}
});

I suggest to rely on pure xml and add to the Imagevie:
android:scaleType="centerCrop"
this will lead to the desired output as drawn.

Related

How to get colour of touched area in canvas - Android

I have created a custom view inside which I have drawn multiple arcs of different colors.
On touching how can I get the color of the touched point?
In Java:
final Bitmap bitmap = Bitmap.createBitmap(customView.getWidth(), customView.getHeight(), Bitmap.Config.ARGB_8888);
customView.draw(new Canvas(bitmap));
customView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int color = bitmap.getPixel((int) event.getX(), (int) event.getY());
return true;
}
});
In Kotlin:
val bitmap = Bitmap.createBitmap(customView.getWidth(), customView.getHeight(), Bitmap.Config.ARGB_8888)
customView.draw(Canvas(bitmap))
customView.setOnTouchListener(View.OnTouchListener { _, event ->
val color = bitmap.getPixel(event.x.toInt(), event.y.toInt())
true
})
Solution to above has two step's
Step 1: Getting the bitmap for your View as canvas is nothing more than a container which holds drawing calls to manipulate a bitmap.As view can update itself based on user event's or some other case then bitmap need's to be updated on onDraw call.
refer here how to do it.
Step 2: And once you get hold of bitmap get the x and y position from event of view
and get specific color of pixel.
refer here how to do it.
Ref :: Bitmap
getPixel(int x, int y)
Returns the Color at the specified location.
Ex
<!--Java-->
int color = bitmapObject.getPixel(10, 10);
<!--Kotlin-->
val color = bitmap.getPixel(10, 10)

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

i have little problem.
I'm getting an image,converting to Bitmap and fill imageview with this Bitmap.
So the problem is,how to take real coordinates(X,Y) of this Bitmap?
For better illustration, i attached an image:
As shown on picture, for e.g. i got an image with Custom Resolution,where user can make an perspective , via yellow points.
So i need to know,how to take real coords of bitmap from ImageView.
What i've made at current moment(but this approach isn't correct):
i take width/height from imageView and recreating new bitmap with this resolution.
Bitmap bt = Bitmap.CreateScaledBitmap(BitmapFactory.DecodeResource(Activity.Resources, Resource.Drawable.test),800,1420,false); //800 width 1420 height
imgView.SetImageBitmap(bt);
Via implementation of TouchListener(methods GetX()/GetY()),i get coords of points(yellow circle's that overlayed on Bitmap), and the problem is that these coordinates not correct.
Also its interesting for me case when i'm stretching bitmap via ScaleType.FitXY on imageView(its possible to take real coords of bitmap) ?
So how can i achieve my goal?
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);

android: place image on display based on where user touches (api 11+)

Hello I am trying to place an imageview on an area where the user touches.
using MotionEvent event
Simply doing imageview.setX(event.getX()) and imageview.setY(event.getY()) is not the complete solution.
I realize these are pixel values, so I tried converting the event values to density independent values using (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, event.getX() , getResources()
.getDisplayMetrics());
but this still does not give me coordinates that match where I touch, when I try to show the imageview at this location.
Also, I am under the suspicion that the imageview draws its upper left corner at these coordinates, when I want the coordinates to be the at center of the imageview.
Insight appreciated
You will most likely want to do something like the following:
If you are trying to find the points on touch event points of a scaled image:
public static 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;
}
public boolean onTouch(View v, MotionEvent event)
{
float[] returnedXY = getPointerCoords((ImageView) v, event);
imageView.setLeft(returnedXY[0] + (imageView.getWidth() /2));
imageView.setTop(returnedXY[1] + (imageView.getHeight() /2));
}
if not, just use the events.getX and getY. You may need to use the getRawX and getRawY of the event.

i want to scale bitmap on ACTION_MOVE android

I want to scale view on touch event of ACTION_MOVE.
all bitmap are in square format. (point1= top+left, point2 =top+right, point3=bottom+left, point4=bottom+right)
i got the all four points.
when i drag the yellow gripper on top of the bitmap , red ball resize according to that (gripper can be move at any direction).
my question:
--> how should i calculate the distance of gripper center point and bitmap (left+top) point1 and scale according to bitmap.
means if i drag the bitmap from top+left corner then it scale/resize from point1,point2,point4 only (bottom+right corner remail at its position).
--> i am using canvas to draw bitmap, is it the rightway to handle bitmap scale/rotate ?
You can get the x,y coordinates on the event ACTION_DOWN and the x',y' coordinates on ACTION_UP. With the two points, you can make your measures (Euclidean Distance, for example).
gripper.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == android.view.MotionEvent.ACTION_DOWN){
x1 = event.getX();
y1 = event.getY();
}
else if(event.getAction() == android.view.MotionEvent.ACTION_UP){
x2 = event.getX();
y2 = event.getY();
}
return false;
}
});
You can also get the left,top position of the bitmap with getLeft(),getTop() methods (but note that these methods return the position relative to the View's parent layout).
There is an Matrix parameter on the createBitmap method that will allow you to resize your Bitmap and so you can store it with the resolution you want. See how here (it's an excellent tutorial, by the way). You probably already know how to do that, but I see no problem in sharing it anyway =P.
Hope it helps

Draw Circle is inaccurate

In my app, when the user touches the screen, a circle is drawn, and if a circle has already been drawn at point a, then another circle cannot be drawn there.
when I use canvas.drawCircle(...), it's innacurate. if I tap close to the top of the screen, then it is just very minutely missing where I tapped it (slightly to the left or right). The farther I go down the farther up my circle is from where I touched. If I'm touching the left side of the screen, the circle goes to the right of the touch point, and if I touch the right side of the screen, the circle is on the left.
Here's my code:
public void onCreate(...){
super.onCreate();
setcontentView(...);
drawnX = new ArrayList<Float>();
drawnY = new ArrayList<Float>();
layout = (ImageView)findViewById(R.id.layout);
layout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent me) {
newY = me.getY();
newX = me.getX();
int action = me.getAction();
if (action==0){
Log.v(tag, "New Touch");
Log.i(tag, String.valueOf("Action " + action +
" happened at X,Y: " + "("+newX+","+newY + ")"));
getDistance(newX, newY);
}
return true;
}
});
#Override
public void onResume(){
super.onResume();
display = getWindowManager().getDefaultDisplay();
screenHeight = display.getHeight();
screenWidth = display.getWidth();
bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
paint = new Paint();
circleRadius = screenHeight/50;
}
public void getDistance(float xNew, float yNew){
// here I compare the new touch x and y values with the x and y values saved
// in the Array Lists I made above. If distance is > circleRadius, then:
drawPoint(xNew, yNew)
}
public void drawPoint(final float x, final float y){
minDistance = Float.NaN;
new Thread(new Runnable(){
#Override
public void run(){
paint.setColor(Color.RED);
canvas.drawCircle(x, y, circleRadius, paint);
layout.post(new Runnable(){
#Override
public void run(){
layout.setImageDrawable(new BitmapDrawable(bitmap));
//I have also tried setImageBitmap and setBackgroundDrawable
}
});
}
}).start();
}
Int the process of all of this, I also do some logging in the drawPoint, and it shows that the x and y coordinates match that which are gotten in the onTouch.
I've also tried maknig it a LinearLayout, but that had the same effect.
And, the bitmap size matches the screen size and canvas size. also, for testing I did
canvas.drawARGB(...)
and it covered the whole screen, so I know it's not just that the bitmap is not stretching to the bottom. The layout's height is less than the height of everything else, and the width of the layout is the same as everything else, but when I use layout.getHeight and layout.getWidth in my onResume, they always return 0, so I can't really use that.
I really have no clue what's causing it. I also tried it on two emulators and got the same response. Any help would be greatly appreciated.
Also, if I tap on the drawn circle (toward the bottom of the screen), another circle will then be drawn above that one, but if I tap where I previously tapped, then a new circle will not be drawn, which really is what's suppose to happen. the circle is just not showing on the screen correctly.
I found the answer.
Oddly enough, even though the width of the bitmap matched the width of the layout, when I did a little more testing, I found the dimensions didn't actually fit together on the left and right either.
I wasn't using the layout.getWidth() and layout.getHeight() due to it returning 0 in onResume()
But, I thought the different height from display.getHeight() very well may be causing the problem, so I did essentially:
new Handler().postDelayed(getLayoutSizeRunnable, 5000);
where getLayoutSizeRunnable was essentially:
screenWidth = layout.getWidth();
screenHeight = layout.getHeight();
Then everything worked perfectly.
And for the usage in my app, I'll use an if statement so the first time a touch point is made, the layout size will be calculated, and the bitmap will be created based on it.

Categories

Resources