There is a problem here: if the user pans too far, you reject the entire pan and do nothing. It means that if you're near the edge of the image, a quick swipe will often not move the image at all.  I prefer to structure code like this as follows:

  posX += positions.dx;
  if (posX > 0)
    posX = 0;
  else if (posX < limitX)
    posX = limitX;

  // Do the same thing for y