title: How to get position of pixel of bitmap touched in imageview
body: <p>There have been many questions exactly like this. I have gone through them but couldn't get it working.</p>
  
  <p>My Activity</p>
  
  <pre><code>public class MainActivity extends Activity {
  
  private static final String    TAG = "GT:MA";
  private ImageView imageView;
  Bitmap original;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      Log.i(TAG, "in onCreate method");
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
  
      imageView = (ImageView) this.findViewById(R.id.image);
  
      BitmapFactory.Options options = new BitmapFactory.Options();
      options.inScaled = false;
      int resId = getResources().getIdentifier("beerl", "drawable", "com.sivaprasadvarma.grabtouch");
      original = BitmapFactory.decodeResource(getResources(), resId, options);
      Log.i(TAG, "original size after decoding: "
              + String.valueOf(original.getWidth()) + " / "
              + String.valueOf(original.getHeight()));
  
      imageView.setImageBitmap(original);
      imageView.setOnTouchListener(myOnTouchSelectingListener);
  }
  
  
  // I've implemented diff methods in answers here
  // http://stackoverflow.com/questions/4933612/how-to-convert-coordinates-of-the-image-view-to-the-coordinates-of-the-bitmap
  OnTouchListener myOnTouchSelectingListener = 
          new OnTouchListener() {
  
              @Override
              public boolean onTouch(View view, MotionEvent event) {
                      Log.i(TAG, "---------------------");                    
  
                      // 1st method
                      float eventX = event.getX();
                      float eventY = event.getY();
                      float[] eventXY = new float[] {eventX, eventY};
  
                      Log.i(TAG, "1: touched position: "  + String.valueOf(eventX) + " / " 
                              + String.valueOf(eventY));
  
  
                      //2nd method
                      Matrix invertMatrix = new Matrix();
                      ((ImageView)view).getImageMatrix().invert(invertMatrix);
                      invertMatrix.mapPoints(eventXY);
                      int x = Integer.valueOf((int)eventXY[0]);
                      int y = Integer.valueOf((int)eventXY[1]);
  
                      Log.i(TAG,  "2: Inverted touch position by invMatrix: "
                              + String.valueOf(x) + " / " 
                              + String.valueOf(y));
  
  
  
                      Drawable imgDrawable = ((ImageView)view).getDrawable();
                      Bitmap bitmap = ((BitmapDrawable)imgDrawable).getBitmap();                      
                      // make sure they are of same size
                      Log.i(TAG, "from getter drawable size: "
                              + String.valueOf(bitmap.getWidth()) + " / " 
                              + String.valueOf(bitmap.getHeight()));                      
                      Log.i(TAG, "actual drawable size: "
                              + String.valueOf(original.getWidth()) + " / "
                              + String.valueOf(original.getHeight()));
  
                      //Limit x, y range within bitmap
                      if(x &lt; 0){
                          x = 0;
                      }else if(x &gt; bitmap.getWidth()-1){
                          x = bitmap.getWidth()-1;
                      }
                      if(y &lt; 0){
                          y = 0;
                      }else if(y &gt; bitmap.getHeight()-1){
                          y = bitmap.getHeight()-1;
                      }
  
                      // mapping them back to bitmap coordinates
                      Rect imageBounds = imgDrawable.getBounds();
  
                      //original height and width of the bitmap
                      int intrinsicHeight = imgDrawable.getIntrinsicHeight();
                      int intrinsicWidth = imgDrawable.getIntrinsicWidth();
                      Log.i(TAG, "intrinsic width / height: "
                              + String.valueOf(intrinsicWidth) + " / "
                              + String.valueOf(intrinsicHeight));
  
                      //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
                      float heightRatio = intrinsicHeight / scaledHeight;
                      float widthRatio = intrinsicWidth / scaledWidth;
  
  
                      // 3rd method
                      //get the distance from the left and top of the image bounds
                      int scaledImageOffsetX = Math.round(event.getX() - imageBounds.left);
                      int scaledImageOffsetY = Math.round(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 = Math.round(scaledImageOffsetX * widthRatio);
                      int originalImageOffsetY = Math.round(scaledImageOffsetY * heightRatio);
  
                      Log.i(TAG,  "3: mapped position: "
                              + String.valueOf(originalImageOffsetX) + " / " 
                              + String.valueOf(originalImageOffsetY));
  
                      //4th method
                      int inv_scaledImageOffsetX = x - imageBounds.left;
                      int inv_scaledImageOffsetY = y - imageBounds.top;
                      int inv_originalImageOffsetX = Math.round(inv_scaledImageOffsetX * widthRatio);
                      int inv_originalImageOffsetY = Math.round(inv_scaledImageOffsetY * heightRatio);
  
                      Log.i(TAG,  "4: inv mapped position: "
                              + String.valueOf(inv_originalImageOffsetX) + " / " 
                              + String.valueOf(inv_originalImageOffsetY));
  
  
  
                      int touchedRGB = bitmap.getPixel(x, y);
                      int org_touchedRGB = original.getPixel(x, y);
  
                      // 5th method
                      float[] point_coords = getPointerCoords((ImageView)view, event);
                      Log.i(TAG,  "5: pointer coords position: "
                              + String.valueOf(Math.round(point_coords[0])) + " / " 
                              + String.valueOf(Math.round(point_coords[1])));
  
  
                      Log.i(TAG, "getter touched color: " + "#" + Integer.toHexString(touchedRGB));
                      Log.i(TAG, "original touched color: " + "#" + Integer.toHexString(org_touchedRGB));
                      Log.i(TAG, "---------------------");
                      return true;
              }
          };
  
          private final 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;
          }
  
  
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
  }
  }
  </code></pre>
  
  <p>My Layout</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:gravity="center"
      android:orientation="horizontal" &gt;  
       &lt;ImageView
           android:id="@+id/image"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center"
           android:contentDescription="@string/descImage"
           android:src="@drawable/beerl" /&gt;
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p>Basically I've implemented 5 ways to get the position of touched pixel in the activity and i'm logging them and I have only a ImageView in my layout. The size of my image is 960x540. so when i'm touching at approx'ly middle of the image I should get 
  value close to 480/270, but i'm  getting following in the log when i touch close to middle of image</p>
  
  <pre><code>7-16 11:00:50.097: I/GT:MA(3273): ---------------------
  07-16 11:00:50.097: I/GT:MA(3273): 1: touched position: 330.0 / 166.0
  07-16 11:00:50.097: I/GT:MA(3273): 2: Inverted touch position by invMatrix: 330 / 166
  07-16 11:00:50.097: I/GT:MA(3273): from getter drawable size: 960 / 540
  07-16 11:00:50.097: I/GT:MA(3273): actual drawable size: 960 / 540
  07-16 11:00:50.097: I/GT:MA(3273): intrinsic width / height: 640 / 360
  07-16 11:00:50.097: I/GT:MA(3273): 3: mapped position: 330 / 166
  07-16 11:00:50.097: I/GT:MA(3273): 4: inv mapped position: 330 / 166
  07-16 11:00:50.097: I/GT:MA(3273): 5: pointer coords position: 330 / 166
  07-16 11:00:50.097: I/GT:MA(3273): getter touched color: #ffcd7d27
  07-16 11:00:50.097: I/GT:MA(3273): original touched color: #ffcd7d27
  07-16 11:00:50.097: I/GT:MA(3273): ---------------------
  </code></pre>
  
  <p>when I click near bottom right of image i'm getting the following in log</p>
  
  <pre><code>07-16 11:03:31.419: I/GT:MA(3273): ---------------------
  07-16 11:03:31.419: I/GT:MA(3273): 1: touched position: 635.0 / 348.0
  07-16 11:03:31.419: I/GT:MA(3273): 2: Inverted touch position by invMatrix: 635 / 348
  07-16 11:03:31.419: I/GT:MA(3273): from getter drawable size: 960 / 540
  07-16 11:03:31.419: I/GT:MA(3273): actual drawable size: 960 / 540
  07-16 11:03:31.419: I/GT:MA(3273): intrinsic width / height: 640 / 360
  07-16 11:03:31.419: I/GT:MA(3273): 3: mapped position: 635 / 348
  07-16 11:03:31.419: I/GT:MA(3273): 4: inv mapped position: 635 / 348
  07-16 11:03:31.429: I/GT:MA(3273): 5: pointer coords position: 635 / 348
  07-16 11:03:31.429: I/GT:MA(3273): getter touched color: #ff242722
  07-16 11:03:31.429: I/GT:MA(3273): original touched color: #ff242722
  07-16 11:03:31.429: I/GT:MA(3273): ---------------------
  </code></pre>
  
  <p>the entire project is <a href="https://docs.google.com/file/d/0B-JzM7zJMKZlYV9qSjJjek9xR0E/edit?usp=sharing" rel="nofollow">here</a>[zip] in case if you want to take a clear look a the whole thing.</p>
  
  <p>Why are the intrinsicWidth and intrinsicHeight different from actual width and height of BitmapDrawable. It looks like I'm getting correct value's If we assume that image has size intrinsicWidth X intrinsicHeight. Why is it so ? How to get correct bitmap coordinates of the pixel touched.</p>