[cocoa-touch] 사용자가 화면을 집을 때 UIImage 객체를 확대 / 축소하는 방법은 무엇입니까?

사용자가 내 응용 프로그램에서 표준 핀치 작업을 수행 할 때 UIImage 개체를 확대 / 축소하고 싶습니다. 해당 세부 사항이 어떤 식 으로든 도움이된다면 현재 UIImageView를 사용하여 이미지를 표시하고 있습니다.

나는 이것을하는 방법을 알아 내려고 노력하고 있지만 지금까지 그러한 운이 없습니다.

단서가 있습니까?



답변

이를 수행하는 또 다른 쉬운 방법 UIImageViewUIScrollView. 여기 에서 설명했듯이 스크롤 뷰의 contentSize를 UIImageView's크기 와 동일하게 설정해야 합니다. 컨트롤러 인스턴스를 스크롤 뷰의 델리게이트로 설정하고 핀치 확대 및 이미지 패닝을 허용 하는 viewForZoomingInScrollView:scrollViewDidEndZooming:withView:atScale:메서드를 구현합니다 . 이것은 전체 웹보기의 오버 헤드가 없기 때문에 Ben의 솔루션이 약간 더 가벼운 방식으로 수행하는 작업입니다.

발생할 수있는 한 가지 문제는 스크롤 뷰 내의 크기 조정이 이미지에 적용된 변환 형식으로 제공된다는 것입니다. 이는 높은 줌 배율에서 흐릿함을 유발할 수 있습니다. 다시 그릴 수있는 항목의 경우 핀치 제스처가 완료된 후 더 선명한 디스플레이를 제공하기 위해 여기 에서 제 제안을 따를 수 있습니다 . 그 시점에서 hniels의 솔루션을 사용하여 이미지의 크기를 조정할 수 있습니다.


답변

다른 사람들이 설명했듯이 가장 쉬운 해결책은 UIImageView를 UIScrollView에 넣는 것입니다. Interface Builder .xib 파일에서이 작업을 수행했습니다.

viewDidLoad에서 다음 변수를 설정합니다. 컨트롤러를 UIScrollViewDelegate로 설정하십시오.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.scrollView.minimumZoomScale = 0.5;
    self.scrollView.maximumZoomScale = 6.0;
    self.scrollView.contentSize = self.imageView.frame.size;
    self.scrollView.delegate = self;
}

확대 / 축소하려는 imageView를 반환하려면 다음 메서드를 구현해야합니다.

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return self.imageView;
}

iOS9 이전 버전에서는 다음과 같은 빈 델리게이트 메서드를 추가해야 할 수도 있습니다.

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
}

애플 문서는 이 작업을 수행하는 방법을 설명하는 좋은 일을한다 :


답변

UIImageView에 대한 Shefali의 솔루션은 훌륭하게 작동하지만 약간의 수정이 필요합니다.

- (void)pinch:(UIPinchGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateEnded
        || gesture.state == UIGestureRecognizerStateChanged) {
        NSLog(@"gesture.scale = %f", gesture.scale);

        CGFloat currentScale = self.frame.size.width / self.bounds.size.width;
        CGFloat newScale = currentScale * gesture.scale;

        if (newScale < MINIMUM_SCALE) {
            newScale = MINIMUM_SCALE;
        }
        if (newScale > MAXIMUM_SCALE) {
            newScale = MAXIMUM_SCALE;
        }

        CGAffineTransform transform = CGAffineTransformMakeScale(newScale, newScale);
        self.transform = transform;
        gesture.scale = 1;
    }
}

(Shefali의 솔루션은 꼬집는 동안 연속적으로 확장되지 않는다는 단점이 있습니다. 또한 새 핀치를 시작할 때 현재 이미지 배율이 재설정되었습니다.)


답변

아래 코드는 UIScrollView를 사용하지 않고 UIImageView를 확대 / 축소하는 데 도움이됩니다.

-(void)HandlePinch:(UIPinchGestureRecognizer*)recognizer{
    if ([recognizer state] == UIGestureRecognizerStateEnded) {
        NSLog(@"======== Scale Applied ===========");
        if ([recognizer scale]<1.0f) {
            [recognizer setScale:1.0f];
        }
        CGAffineTransform transform = CGAffineTransformMakeScale([recognizer scale],  [recognizer scale]);
        imgView.transform = transform;
    }
}


답변

절대로 UIImage. 이제까지.

대신에의 확대 및 축소하고 view그 표시합니다 UIImage.

이 특정한 경우에, 당신은 사용자 정의 만들 수 chould UIViewA, 이미지를 표시하는 사용자 정의 그리기를 UIImageView당신을 위해 이미지를 표시하는, 또는 UIWebView몇 가지 추가적인 HTML을해야 할 것이다 그것을 백업 할 수 있습니다.

모든 경우에, 당신은 구현해야합니다 touchesBegan, touchesMoved그리고 같은 사용자가 (줌, 팬 등)을 수행하려고 결정 할 수 있습니다.


답변

다음은 UIWebView를 사용할 필요가없는 이전에 사용한 솔루션입니다.

- (UIImage *)scaleAndRotateImage(UIImage *)image
{
    int kMaxResolution = 320; // Or whatever

    CGImageRef imgRef = image.CGImage;

    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);


    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    if (width > kMaxResolution || height > kMaxResolution) {
        CGFloat ratio = width/height;
        if (ratio > 1) {
            bounds.size.width = kMaxResolution;
            bounds.size.height = bounds.size.width / ratio;
        }
        else {
            bounds.size.height = kMaxResolution;
            bounds.size.width = bounds.size.height * ratio;
        }
    }

    CGFloat scaleRatio = bounds.size.width / width;
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    UIImageOrientation orient = image.imageOrientation;
    switch(orient) {

        case UIImageOrientationUp: //EXIF = 1
            transform = CGAffineTransformIdentity;
            break;

        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;

        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;

        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];

    }

    UIGraphicsBeginImageContext(bounds.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    }
    else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }

    CGContextConcatCTM(context, transform);

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

이 기사는 Apple 지원 ( http://discussions.apple.com/message.jspa?messageID=7276709#7276709) 에서 찾을 수 있습니다.


답변

Shafali 및 JRV의 답변은 패닝 및 핀치로 확대 / 축소를 포함하도록 확장되었습니다.

#define MINIMUM_SCALE 0.5
#define MAXIMUM_SCALE 6.0
@property CGPoint translation;


- (void)pan:(UIPanGestureRecognizer *)gesture {
    static CGPoint currentTranslation;
    static CGFloat currentScale = 0;
    if (gesture.state == UIGestureRecognizerStateBegan) {
        currentTranslation = _translation;
        currentScale = self.view.frame.size.width / self.view.bounds.size.width;
    }
    if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateChanged) {

        CGPoint translation = [gesture translationInView:self.view];

        _translation.x = translation.x + currentTranslation.x;
        _translation.y = translation.y + currentTranslation.y;
        CGAffineTransform transform1 = CGAffineTransformMakeTranslation(_translation.x , _translation.y);
        CGAffineTransform transform2 = CGAffineTransformMakeScale(currentScale, currentScale);
        CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
        self.view.transform = transform;
    }
}


- (void)pinch:(UIPinchGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateChanged) {
//        NSLog(@"gesture.scale = %f", gesture.scale);

        CGFloat currentScale = self.view.frame.size.width / self.view.bounds.size.width;
        CGFloat newScale = currentScale * gesture.scale;

        if (newScale < MINIMUM_SCALE) {
            newScale = MINIMUM_SCALE;
        }
        if (newScale > MAXIMUM_SCALE) {
            newScale = MAXIMUM_SCALE;
        }

        CGAffineTransform transform1 = CGAffineTransformMakeTranslation(_translation.x, _translation.y);
        CGAffineTransform transform2 = CGAffineTransformMakeScale(newScale, newScale);
        CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
        self.view.transform = transform;
        gesture.scale = 1;
    }
}