0
votes

I am building a photo app for iPhone which allows the user to take a photo with the camera or grab one from the Camera Roll, then pan and zoom this image as needed in a UIScrollView. The user then taps a button to save the image. I am having trouble with the key method that returns the exact center of the visible area of an imageview embedded in the scrollview. I need this method to allow for variations in the dimensions of the device screen (i.e., iPhone 4 vs 5), as well as for variations in the size, aspect ratio and zoom scale of the source image.

As an example, I need to get this to work for the following:

  • iPhone 5 with screen dimensions that are 320 X 568
  • Scrollview frame size of 320 X 568
  • An image with dimensions 380 width and 284 height
  • Zoom scale of 3.0

Alternatively, I also need for it to work for this:

  • iPhone 4 with screen dimensions of 320 X 480
  • Scrollview frame size of 320 X 480
  • An image with dimensions 640 width and 1048 height
  • Zoom scale of 1.3

The following is my current code, which tries to account for variations in the screen's dimensions and the image's dimensions, but it does not work for both iPhone 4 and 5, and for all types of images, such as those in portrait or landscape format. Is there a simpler way to get the center point of the visible portion of a scrollview? I need a clearer understanding of how to interpret and manipulate the properties of a view, such as the bounds.origin and bounds.size and use content size and zoom scale in the scrollview.

I have looked at various questions that are similar but none of these seem to account adequately for all variations in device or image aspect ratio or size. Any help would be greatly appreciated!

Similar questions

How can I determine the area currently visible in a scrollview and determine the center?

Getting the right coordinates of the visible part of a UIImage inside of UIScrollView

- (CGPoint)centerOfVisibleFrame:(UIImage *)image inScrollView:(UIScrollView *)scrollView
{
    CGPoint frameCenter;

    CGFloat zoomScale = scrollView.zoomScale;

    // First determine the dimensions of the device
    CGSize deviceFrameSize = [UIScreen mainScreen].bounds.size;

    // Need to determine the scale factor for adjusting the image to full width/full height
    CGFloat imageDeviceAspectFitScale;

    // Compare the aspect ratio (height / width) of the device to the aspect ratio of the image
    CGFloat deviceAspectRatio = deviceFrameSize.height / deviceFrameSize.width;
    CGFloat imageAspectRatio = image.size.height / image.size.width;

    // If the device's aspect ratio is greater than the image aspect ratio
    if (deviceAspectRatio > imageAspectRatio)
    {
        // Set the imageDeviceAspectFitScale for full width
        imageDeviceAspectFitScale = image.size.width / deviceFrameSize.width;
    }
    // Otherwise the image's aspect ratio is greater than the device aspect ratio
    else
    {
        // Set the imageDeviceAspectFitScale for full height
        imageDeviceAspectFitScale = image.size.height / deviceFrameSize.height;
    }

    // Create the frame for the image at full width or full height
    CGSize imageAspectFitSize;
    imageAspectFitSize.width = image.size.width / imageDeviceAspectFitScale;
    imageAspectFitSize.height = image.size.height / imageDeviceAspectFitScale;

    // Calculate the vertical and horizontal offset to adjust the coordinates of the
    // image center to account for greater device height or device width
    CGFloat verticalOffset = deviceFrameSize.height - imageAspectFitSize.height;
    CGFloat horizontalOffset = deviceFrameSize.width - imageAspectFitSize.width;

    if (self.debug) NSLog(@"verticalOffset = %f horizontalOffset = %f", verticalOffset, horizontalOffset);

    if (self.debug) NSLog(@"image.size.width: %f image.size.height: %f", image.size.width, image.size.height);

    if (self.debug) NSLog(@"scrollView.frame.size w: %f h: %f", scrollView.frame.size.width, scrollView.frame.size.height);

    if (self.debug) NSLog(@"scrollView.bounds.size.width: %f scrollView.bounds.size.height: %f",
                          scrollView.bounds.size.width, scrollView.bounds.size.height);

    if (self.debug) NSLog(@"scrollView.contentSize w=%f h=%f", scrollView.contentSize.width, scrollView.contentSize.height);

    // imageRect represents the coordinate space for the image, adjusted for zoom scale
    CGRect imageRect;

    // First use the visible frame's origin to determine the top left corner of the visible rectangle
    imageRect.origin.x = scrollView.contentOffset.x;
    imageRect.origin.y = scrollView.contentOffset.y;

    if (self.debug) NSLog(@"imageRect.origin x = %f y = %f", imageRect.origin.x, imageRect.origin.y);

    // Adjust the image rect for zoom - Multiply by zoom scale
    imageRect.size.width = image.size.width * zoomScale;
    imageRect.size.height = image.size.height * zoomScale;

    if (self.debug) NSLog(@"Zoomed imageRect.size width = %f height = %f", imageRect.size.width, imageRect.size.height);

    // Then scale the image down to fit into the device frame
    // Divide by the image device aspect fit scale
    imageRect.size.width = imageRect.size.width / imageDeviceAspectFitScale;
    imageRect.size.height = imageRect.size.height / imageDeviceAspectFitScale;

    if (self.debug) NSLog(@"CVF Aspect fit imageRect.size width = %f height = %f", imageRect.size.width, imageRect.size.height);

    // Then calculate the frame center by using the x and y dimensions of the DEVICE frame
    frameCenter.x = imageRect.origin.x + (deviceFrameSize.width / 2);
    frameCenter.y = imageRect.origin.y + (deviceFrameSize.height / 2);

    // Scale back to original image dimensions from zoom
    frameCenter.x = frameCenter.x / zoomScale;
    frameCenter.y = frameCenter.y / zoomScale;

    if (self.debug) NSLog(@"frameCenter.x = %f frameCenter.y = %f", frameCenter.x, frameCenter.y);

    // Scale back up for the aspect fit scale
    frameCenter.x = frameCenter.x * imageDeviceAspectFitScale;
    frameCenter.y = frameCenter.y * imageDeviceAspectFitScale;

    // Correct the coordinates for horizontal and vertical offset
    frameCenter.x = frameCenter.x - (horizontalOffset);
    frameCenter.y = frameCenter.y - (verticalOffset);

    if (self.debug) NSLog(@"CVF frameCenter.x = %f frameCenter.y = %f", frameCenter.x, frameCenter.y);

    return frameCenter;


}
1

1 Answers

0
votes

basically this gives you the visible rect of your scrollview.

CGRect visibleRect = [yourScrollView convertRect:yourScrollView.bounds toView:yourImageview];

or

CGRect visibleRect;
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = scrollView.frame.size;

please have a look this question and answers for more details. Getting the visible rect of an UIScrollView's content.

as long as you know the rect you can easily calculate center point.