How to get the position of a picture inside an ImageView?
Asked Answered
C

4

11

I have a gallery of images with different sizes. Each image is displayed inside an ImageView sequentially (through OnTouchListener). I need to know the position of the frame of the picture I'm showing relatives to the ImageView but with the testing I've done I've only gotten the coordinates of ImageView. Any idea?

enter image description here

I need the values of (x1, y1) and (x2, y2).

Thanks in advance.

This is my class:

public class PuzzleView extends ImageView {

protected Paint currentPaint;    

protected boolean drawRect = false;    
protected float left;
protected float top;
protected float right;
protected float bottom;

protected float pixelX;
protected float pixelY;

protected int nChunksX = 5;
protected int nChunksY = 5;

protected int currentWidth = 0;
protected int currentHeight = 0;

public PuzzleView(Context context, AttributeSet attrs) {
    super(context, attrs);

    currentPaint = new Paint();
    currentPaint.setDither(true);
    currentPaint.setColor(0xFF00CC00);  
    currentPaint.setStyle(Paint.Style.STROKE);
    currentPaint.setStrokeJoin(Paint.Join.ROUND);
    currentPaint.setStrokeCap(Paint.Cap.ROUND);
    currentPaint.setStrokeWidth(2);                           
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    float chunkWidth = currentWidth / nChunksX;
    float chunkHeight = currentHeight / nChunksY;

    float posX = ((int)(pixelX / chunkWidth)) * chunkWidth;
    float posY = ((int)(pixelY / chunkHeight)) * chunkHeight;

    canvas.drawRect(posX, posY, posX + chunkWidth, posY + chunkHeight, currentPaint);

    Rect rect = this.getDrawable().getBounds();
    canvas.drawRect(rect, currentPaint);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    // Get image matrix values and place them in an array
    float[] f = new float[9];
    getImageMatrix().getValues(f);

    // Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
    final float scaleX = f[Matrix.MSCALE_X];
    final float scaleY = f[Matrix.MSCALE_Y];

    // Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
    final Drawable d = getDrawable();
    final int origW = d.getIntrinsicWidth();
    final int origH = d.getIntrinsicHeight();

    // Calculate the actual dimensions
    final int actW = Math.round(origW * scaleX);
    final int actH = Math.round(origH * scaleY);

    currentWidth = actW;
    currentHeight = actH;
}

public boolean isDrawRect() {
    return drawRect;
}

public void setDrawRect(boolean drawRect) {
    this.drawRect = drawRect;
}

public float getLeftRect() {
    return left;
}

public void setLeftRect(float left) {
    this.left = left;
}

public float getTopRect() {
    return top;
}

public void setTopRect(float top) {
    this.top = top;
}

public float getRightRect() {
    return right;
}

public void setRightRect(float right) {
    this.right = right;
}

public float getBottomRect() {
    return bottom;
}

public void setBottomRect(float bottom) {
    this.bottom = bottom;
}

public float getPixelX() {
    return pixelX;
}

public void setPixelX(float pixelX) {
    this.pixelX = pixelX;
}

public float getPixelY() {
    return pixelY;
}

public void setPixelY(float pixelY) {
    this.pixelY = pixelY;
}

public int getChunksX() {
    return nChunksX;
}

public void setChunksX(int nChunksX) {
    this.nChunksX = nChunksX;
}

public int getChunksY() {
    return nChunksY;
}

public void setChunksY(int nChunksY) {         
    this.nChunksY = nChunksY;
}
}

For now, the source image is defined in XML file:

<com.jocajica.shakepic.PuzzleView
    android:id="@+id/imageViewSelected"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:contentDescription="@string/image_selected"
    android:src="@android:drawable/progress_indeterminate_horizontal" />

I need to draw a grid over the image.

Chimere answered 24/4, 2013 at 13:26 Comment(3)
What's wrong with getTop/getLeft/getBottom/getRight ?Suanne
@blackbelt I believe these will return the coordinates of the ImageView within its container. The OP wants to know the offset of the actual image within ImageViewMaiga
Exactly. I need to know the offset of the current image and the getTop/getLeft/getBottom/getRight only return the coordinates of the ImageView within its container.Chimere
N
17

According to Jacob Nordfalk's link, I was able to produce a static method allowing you to get the image position and dimensions from an ImageView.

/**
 * Returns the bitmap position inside an imageView.
 * @param imageView source ImageView
 * @return 0: left, 1: top, 2: width, 3: height
 */
public static int[] getBitmapPositionInsideImageView(ImageView imageView) {
    int[] ret = new int[4];

    if (imageView == null || imageView.getDrawable() == null)
        return ret;

    // Get image dimensions
    // Get image matrix values and place them in an array
    float[] f = new float[9];
    imageView.getImageMatrix().getValues(f);

    // Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
    final float scaleX = f[Matrix.MSCALE_X];
    final float scaleY = f[Matrix.MSCALE_Y];

    // Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
    final Drawable d = imageView.getDrawable();
    final int origW = d.getIntrinsicWidth();
    final int origH = d.getIntrinsicHeight();

    // Calculate the actual dimensions
    final int actW = Math.round(origW * scaleX);
    final int actH = Math.round(origH * scaleY);

    ret[2] = actW;
    ret[3] = actH;

    // Get image position
    // We assume that the image is centered into ImageView
    int imgViewW = imageView.getWidth();
    int imgViewH = imageView.getHeight();

    int top = (int) (imgViewH - actH)/2;
    int left = (int) (imgViewW - actW)/2;

    ret[0] = left;
    ret[1] = top;

    return ret;
}
Narcosis answered 14/11, 2014 at 13:14 Comment(4)
This will returns offsets in negative value.Heelpiece
Shouldn't it be: res[2] = left + actW; and res[3] = top + actH;?Siva
No @Zach. res[2] and res[3], as stated in the comment doc, are the width and height and not the right and bottomInhibitory
Thank you Quentis S. and Jacob Nordfalk for the very usefull routine. I took the liberty of changing the return value from an array to a Rect object. See my answer bellow.Byelostok
S
3

You should use getImageMatrix():

float[] imageMatrix = new float[9];
getImageMatrix().getValues(imageMatrix);
scale = imageMatrix[Matrix.MSCALE_X];
transX = imageMatrix[Matrix.MTRANS_X];

See also
Trying to get the display size of an image in an ImageView

Smorgasbord answered 6/9, 2013 at 7:29 Comment(0)
B
2

Thank you Quentis S. and Jacob Nordfalk for the very usefull routine.

I took the liberty of changing the return value from an array to a Rect object.

    /**
 * Returns the bitmap position inside an imageView.
 *
 * @param imageView source ImageView
 * @return Rect position of the bitmap in the ImageView
 */
public static final Rect getBitmapPositionInsideImageView(ImageView imageView)
{
    Rect rect = new Rect();

    if (imageView == null || imageView.getDrawable() == null)
    {
        return rect;
    }

    // Get image dimensions
    // Get image matrix values and place them in an array
    float[] f = new float[9];
    imageView.getImageMatrix().getValues(f);

    // Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
    final float scaleX = f[Matrix.MSCALE_X];
    final float scaleY = f[Matrix.MSCALE_Y];

    // Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
    final Drawable d     = imageView.getDrawable();
    final int      origW = d.getIntrinsicWidth();
    final int      origH = d.getIntrinsicHeight();

    // Calculate the actual dimensions
    final int actW = Math.round(origW * scaleX);
    final int actH = Math.round(origH * scaleY);

    // Get image position
    // We assume that the image is centered into ImageView
    int imgViewW = imageView.getWidth();
    int imgViewH = imageView.getHeight();

    rect.top  = (int) (imgViewH - actH) / 2;
    rect.left = (int) (imgViewW - actW) / 2;

    rect.bottom = rect.top + actH;
    rect.right  = rect.left + actW;

    return rect;
}
Byelostok answered 12/11, 2021 at 13:33 Comment(0)
R
-1

Override the onLayout method

    //inside puzzleView
    float[] matrix = new float[9];
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

        super.onLayout(changed, left, top, right, bottom);
        matrix = getMatrix();

    }    
    public void getMatrix(){
         return matrix;
    }


    private float[] getMatrix() {

        final float[] matrix = new float[9];
        getImageMatrix().getValues(matrix);

        return matrix;
    }

and use this to get values

       // Extract the scale and translation values from the matrix.
       float scaleX = matrix[Matrix.MSCALE_X];
       float scaleY = matrix[Matrix.MSCALE_Y];
       float transX = matrix[Matrix.MTRANS_X];
       float transY = matrix[Matrix.MTRANS_Y];

I hope that this help u

Redhead answered 16/11, 2017 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.