Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 265
Joan Carles Avatar asked Apr 24 '13 13:04

Joan Carles


3 Answers

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;
}
like image 152
Quentin S. Avatar answered Oct 21 '22 20:10

Quentin S.


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;
}
like image 25
Regis St-Gelais Avatar answered Oct 21 '22 21:10

Regis St-Gelais


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

like image 3
Jacob Nordfalk Avatar answered Oct 21 '22 20:10

Jacob Nordfalk