iOS 이미지 방향에 이상한 동작이 있습니다.


94

지난 몇 주 동안 저는 Objective-C에서 이미지 작업을하면서 많은 이상한 동작을 발견했습니다. 첫째, 다른 많은 사람들과 마찬가지로 카메라로 찍은 이미지 (또는 다른 사람의 카메라로 찍은 이미지와 나에게 MMS로 찍은 이미지)가 90도 회전되는 문제가 발생했습니다. 나는 왜 이것이 세계에서 일어나고 있는지 확신하지 못했지만 (그러므로 내 질문 ) 저렴한 해결책을 찾을 수있었습니다.

이번에는 왜 이런 일이 발생 합니까? Apple이 이미지를 회전시키는 이유는 무엇입니까? 카메라를 똑바로 세우고 사진을 찍을 때 위에서 언급 한 코드를 수행하지 않으면 사진을 저장하면 회전하여 저장됩니다. 이제 내 해결 방법은 며칠 전까지 만해도 괜찮 았습니다.

내 응용 프로그램은 이미지의 개별 픽셀, 특히 PNG의 알파 채널을 수정합니다 (따라서 모든 JPEG 변환은 내 시나리오에서 창 밖으로 던져집니다). 며칠 전 해결 코드 덕분에 앱에서 이미지가 제대로 표시되지만 알고리즘이 이미지의 개별 픽셀을 수정할 때 이미지가 회전 된 것으로 생각한다는 것을 알게되었습니다. 따라서 이미지 상단의 픽셀을 수정하는 대신 이미지 측면의 픽셀을 수정합니다 (회전해야한다고 생각하기 때문입니다)! 메모리에서 이미지를 회전하는 방법을 알 수 없습니다. 이상적으로는 해당 imageOrientation플래그를 모두 함께 지우는 것이 좋습니다.

여기 저를 당혹스럽게하는 또 다른 것이 있습니다 ... 제가 사진을 찍을 때, imageOrientation가 3으로 설정되어 있습니다. 제 해결 방법 코드는 이것을 깨닫고 뒤집을 수있을만큼 똑똑해서 사용자가 알아 차리지 못하도록합니다. 또한 이미지를 라이브러리에 저장하는 코드는이를 인식하고 뒤집은 다음 저장하여 카메라 롤에 제대로 표시되도록합니다.

해당 코드는 다음과 같습니다.

NSData* pngdata = UIImagePNGRepresentation (self.workingImage); //PNG wrap 
UIImage* img = [self rotateImageAppropriately:[UIImage imageWithData:pngdata]];   
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);

이 새로 저장된 이미지를 내 앱에로드하면 imageOrientation0이됩니다-정확히 내가보고 싶은 것이므로 회전 해결 방법을 실행할 필요도 없습니다 (참고 : 카메라로 찍은 이미지와 달리 인터넷에서 이미지를로드 할 때 , imageOrientation는 항상 0이므로 완벽한 동작이됩니다.) 어떤 이유로 내 저장 코드가이 imageOrientation플래그 를 지우는 것 같습니다 . 사용자가 사진을 찍고 앱에 추가하자마자 해당 코드를 훔쳐 내 imageOrientation을 지우고 싶었지만 작동하지 않는 것 같습니다. 않습니다 UIImageWriteToSavedPhotosAlbum와 함께 뭔가 특별한을 imageOrientation?

이 문제에 대한 최선의 해결책 imageOrientation은 사용자가 이미지를 찍는 즉시 날려 버리는 것입니다. 나는 Apple이 이유 때문에 회전 동작을 수행했다고 가정합니다. 몇몇 사람들은 이것이 Apple 결함이라고 제안했습니다.

(... 아직 길을 잃지 않았다면 ... Note2 : 가로 사진을 찍으면 인터넷에서 찍은 사진처럼 모든 것이 완벽하게 작동하는 것 같습니다)

편집하다:

다음은 일부 이미지와 시나리오의 실제 모습입니다. 지금까지의 의견을 살펴보면이 이상한 동작은 단순한 iPhone 동작 이상인 것 같습니다.

이것은 내가 휴대 전화로 찍은 사진입니다 (올바른 방향에 유의). 사진을 찍었을 때 휴대 전화에서했던 것과 똑같이 나타납니다.

iPhone에서 찍은 실제 사진

본인에게 이메일을 보낸 후 Gmail에 표시되는 이미지는 다음과 같습니다 (Gmail에서 제대로 처리하는 것처럼 보임).

Gmail에 표시되는 사진

다음은 이미지가 창에서 썸네일로 보이는 것입니다 (올바르게 처리되지 않은 것 같습니다).

Windows 썸네일

그리고 다음은 Windows 사진 뷰어로 열었을 때의 실제 이미지 모습입니다 (여전히 제대로 처리되지 않음).

Windows 사진 뷰어 버전

이 질문에 대한 모든 코멘트를 마친 후, 제가 생각하는 것은 다음과 같습니다. iPhone은 이미지를 찍고 "이를 제대로 표시하려면 90도 회전해야합니다"라고 말합니다. 이 정보는 EXIF ​​데이터에 있습니다. (기본적으로 수직 수직이 아닌 90도 회전해야하는 이유는 모르겠습니다.) 여기에서 Gmail은 EXIF ​​데이터를 읽고 분석하고 올바르게 표시 할 수있을만큼 똑똑합니다. 그러나 Windows는 EXIF ​​데이터를 읽을만큼 똑똑하지 않기 때문에 이미지가 부적절하게 표시됩니다 . 내 가정이 맞습니까?


흥미 롭습니다 ... 그게 사실이라면 촬영 한 이미지가 직각으로 설정되는 이유는 무엇입니까? 나는 이것이 아이폰 결함이 아니라는 것을 알고있다. 왜냐하면 나는 친구 (BlackBerry를 가지고있는)가 이미지를 찍고 MMS가 나에게 그것을 찍을 때 비슷한 행동을 발견했기 때문이다.
Boeckm

카메라가 메타 데이터를 작성하여 90도 회전하고 일부 OS는 해당 메타 데이터를 읽고 나머지는 읽지 않습니다.
HarshIT

꽤 잘 읽었습니다 (아래 @Hadley의 답변 참조-주석에 사용됨). 따라서 내 앱은 EXIF ​​데이터가 포함 된 이미지와 해당 데이터가 포함되지 않은 이미지를 처리 ​​할 수있을만큼 똑똑해야합니다. 그래도 사진을 올바로 찍을 때 방향 플래그가 나타나는 이유를 여전히 이해하지 못합니다. 90도 회전해야한다고?
Boeckm

사진 모드를 세로로 설정하고 카메라를 직각으로 회전하지 않거나 가로 모드가 설정되어 있고 카메라가 직각 위치에서 이미지를 캡처하면 센서가 자동으로 방향을 적절한 방향으로 설정합니다. 확인
HarshIT

1
해결책은 아마도 앱이 메타 데이터를 읽고 이미지를 회전하거나 요구 사항에 따라 메타 데이터를 수정해야한다는 것입니다.
HarshIT

답변:


50

나는 그것에 대해 R & D를했고 모든 이미지 파일에 메타 데이터 속성이 있다는 것을 발견했습니다. 메타 데이터가 일반적으로 Mac이 아닌 다른 OS에서 무시되는 이미지의 방향을 지정하는 경우. 촬영 된 대부분의 이미지는 메타 데이터 속성이 직각으로 설정되어 있습니다. 따라서 Mac은 90도 회전 방식을 보여줍니다. Windows OS에서 동일한 이미지를 적절한 방식으로 볼 수 있습니다.

자세한 내용은이 답변을 읽으십시오. http://graphicssoft.about.com/od/digitalphotography/f/sideways-pictures.htm을

여기에 이미지의 Exif를 읽어보세요 http://www.exifviewer.org/ , 또는 http://regex.info/exif.cgi , 또는 http://www.addictivetips.com/internet-tips/view-complete-exif -metadata-information-of-any-jpeg-image-online /


1
와! EXIF 데이터에 그렇게 많은 정보가 있다는 것을 몰랐습니다! regex.info/exif.cgi 는 놀라운 사이트입니다! 나는 확실히 오늘 밤이 사이트에서 이미지를 가지고 놀 것이다. 모든 시나리오를 테스트해야합니다. 이미지를 똑바로 가져오고, 인터넷에서 가져온 이미지, 회전 한 이미지 등을 테스트해야합니다. 감사합니다!
Boeckm

첫 번째 exif 링크가 이제 끊어지고 두 번째는 exif.regex.info/exif.cgi 로 업데이트되었습니다 . 대답을 편집하려고 시도했지만 @ cj-dennis는 어떤 이유로 그것을 거부했습니다.
라이언

55

카메라에서 이미지를 가져올 때도 같은 문제가 발생했습니다. 다음 코드를 입력하여 수정했습니다. 여기에서 scaleAndRotateImage 메소드를 추가했습니다.

- (void) imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)imageInfo {
            // Images from the camera are always in landscape, so rotate
                    UIImage *image = [self scaleAndRotateImage: [imageInfo objectForKey:UIImagePickerControllerOriginalImage]];
    //then save the image to photo gallery or wherever  
        }


- (UIImage *)scaleAndRotateImage:(UIImage *) image {
    int kMaxResolution = 320;

    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;
}

3
scaleAndRotateImage 코드는 어떻게 생겼습니까? 구글을 한 후 여기있는 것과 같은가요? discussions.apple.com/thread/1537011?start=0&tstart=0
Boeckm

2
와우 ... 하하! 그것은 매우 잘 작동했습니다! 위의 의견에 코드를 사용했습니다. 내 질문에 대한 두 가지 놀라운 답을 얻었습니다! 그건 내가 너무 큰 질문을했다는 뜻인 것 같아요. 정말 고마워요. 몇 가지 심층 테스트를 수행 할 예정이지만 지금까지 방향 문제는 세로 및 가로로 촬영 한 사진에서 잘 작동합니다.
Boeckm

3
내가 거기없는 당신의 방법의 일부이지만, 있고 링크가 여전히 :) 감사 그래서, 내가 나머지를 해결하고 마지막으로 제대로 작동보기를 자르기 내 이미지를 얻을 충분히 생각
빅 스미스

나는 그것이 도움이 기뻐요 .. :)
딜립 라지 쿠마르

이 코드 블록은 원본 이미지의 모양을 유지하지만 방향을 위로 변경합니까?
Junchao Gu

18

빠른 복사 / 붙여 넣기 Dilip의 탁월한 답변 의 신속한 번역 .

import Darwin

class func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {

    let imgRef = imageSource.CGImage;

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

    var bounds = CGRectMake(0, 0, width, height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransformIdentity
    let orient = imageSource.imageOrientation
    let imageSize = CGSizeMake(CGFloat(CGImageGetWidth(imgRef)), CGFloat(CGImageGetHeight(imgRef)))


    switch(imageSource.imageOrientation) {
    case .Up :
        transform = CGAffineTransformIdentity

    case .UpMirrored :
        transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);

    case .Down :
        transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI));

    case .DownMirrored :
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
        transform = CGAffineTransformScale(transform, 1.0, -1.0);

    case .Left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
        transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);

    case .LeftMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);
        transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);

    case .Right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);

    case .RightMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeScale(-1.0, 1.0);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);

    default : ()
    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()

    if orient == .Right || orient == .Left {
        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);

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

1
감사합니다. "let ratio = width / height"는 무엇입니까? 사용? 그 {}의 비율을 사용하여 어떤 장소를 볼 수 없습니다
Pengzhi 저우

18

이번에는 왜 이런 일이 발생합니까? Apple이 이미지를 회전시키는 이유는 무엇입니까?

이에 대한 답은 매우 간단합니다. Apple은 이미지를 회전하지 않습니다. 그것이 혼란이있는 곳입니다.

CCD 카메라는 회전하지 않으므로 항상 가로 모드로 사진을 찍습니다.

애플은 이미지를 회전하는 데 시간을 낭비하는 대신 메가 바이트의 데이터를 섞는 대신 매우 현명한 작업을 수행했습니다. 사진을 촬영 한 방법을 태그 만 지정하면됩니다.

OpenGL은 번역을 매우 쉽게 수행하므로 데이터가 섞이지 않습니다.

따라서 방향 메타 데이터입니다.

자르기, 크기 조정 등을 원할 경우 문제가됩니다.하지만 무슨 일이 일어나고 있는지 알고 나면 매트릭스를 정의하기 만하면 모든 것이 작동합니다.


1
이 설명에 감사드립니다. 한번 생각하면 상식이 있지만 다른 검색 결과는 설명하지 않았습니다.
Dakine83

16

Dilip의 답변에 대한 안전 점검이 포함 된 Swift 4 버전 .

public static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat = 320) -> UIImage? {

    guard let imgRef = imageSource.cgImage else {
        return nil
    }

    let width = CGFloat(imgRef.width)
    let height = CGFloat(imgRef.height)

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: CGFloat(imgRef.width), height: CGFloat(imgRef.height))

    switch(imageSource.imageOrientation) {
    case .up:
        transform = .identity
    case .upMirrored:
        transform = CGAffineTransform
            .init(translationX: imageSize.width, y: 0)
            .scaledBy(x: -1.0, y: 1.0)
    case .down:
        transform = CGAffineTransform
            .init(translationX: imageSize.width, y: imageSize.height)
            .rotated(by: CGFloat.pi)
    case .downMirrored:
        transform = CGAffineTransform
            .init(translationX: 0, y: imageSize.height)
            .scaledBy(x: 1.0, y: -1.0)
    case .left:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: 0, y: imageSize.width)
            .rotated(by: 3.0 * CGFloat.pi / 2.0)
    case .leftMirrored:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: imageSize.height, y: imageSize.width)
            .scaledBy(x: -1.0, y: 1.0)
            .rotated(by: 3.0 * CGFloat.pi / 2.0)
    case .right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: imageSize.height, y: 0)
            .rotated(by: CGFloat.pi / 2.0)
    case .rightMirrored:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(scaleX: -1.0, y: 1.0)
            .rotated(by: CGFloat.pi / 2.0)
    }

    UIGraphicsBeginImageContext(bounds.size)
    if let context = UIGraphicsGetCurrentContext() {
        if orient == .right || orient == .left {
            context.scaleBy(x: -scaleRatio, y: scaleRatio)
            context.translateBy(x: -height, y: 0)
        } else {
            context.scaleBy(x: scaleRatio, y: -scaleRatio)
            context.translateBy(x: 0, y: -height)
        }

        context.concatenate(transform)
        context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))
    }

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageCopy
}

(bounds.size.height, bounds.size.width) = (bounds.size.width, bounds.size.height)변수를 저장소로 만들지 않고도 할 수 있습니다 .
Almas Sapargali

때때로 이미지 크기를 조정 한 후 이미지 하단에 흰색 선이 나타나는 문제가있었습니다. 이것은 CGFloat가 충분히 정확하지 않은 것처럼 보이기 때문입니다. 나는 이것을 수정 bounds.size.height.round()하고bounds.size.width.round()
ndreisg

13

iPhone / iPad에서 생성 된 모든 이미지는 실제 방향을 지정하는 EXIF ​​Orientation 태그 (Exif.Image.Orientation)와 함께 Landscape Left로 저장됩니다.

값은 다음과 같습니다. 1 : 가로 왼쪽 6 : 세로 보통 3 : 가로 오른쪽 4 : 세로 거꾸로

IOS에서는 EXIF ​​정보가 제대로 읽히고 촬영 한 것과 같은 방식으로 이미지가 표시됩니다. 그러나 Windows에서는 EXIF ​​정보가 사용되지 않습니다.

김프에서 이러한 이미지 중 하나를 열면 이미지에 회전 정보가 있다고 표시됩니다.


8

Xamarin을 사용하는 다른 사람을 위해 Dilip의 훌륭한 답변에 대한 C # 번역 과 Swift 번역에 대한 thattyson에게 감사드립니다 .

public static UIImage RotateCameraImageToProperOrientation(UIImage imageSource, nfloat maxResolution) {

    var imgRef = imageSource.CGImage;

    var width = (nfloat)imgRef.Width;
    var height = (nfloat)imgRef.Height;

    var bounds = new CGRect(0, 0, width, height);

    nfloat scaleRatio = 1;

    if (width > maxResolution || height > maxResolution) 
    {
        scaleRatio = (nfloat)Math.Min(maxResolution / bounds.Width, maxResolution / bounds.Height);
        bounds.Height = bounds.Height * scaleRatio;
        bounds.Width = bounds.Width * scaleRatio;
    }

    var transform = CGAffineTransform.MakeIdentity();
    var orient = imageSource.Orientation;
    var imageSize = new CGSize(imgRef.Width, imgRef.Height);
    nfloat storedHeight;

    switch(imageSource.Orientation) {
        case UIImageOrientation.Up:
            transform = CGAffineTransform.MakeIdentity();
            break;

        case UIImageOrientation.UpMirrored :
            transform = CGAffineTransform.MakeTranslation(imageSize.Width, 0.0f);
            transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
            break;

        case UIImageOrientation.Down :
            transform = CGAffineTransform.MakeTranslation(imageSize.Width, imageSize.Height);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI);
            break;

        case UIImageOrientation.DownMirrored :
            transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Height);
            transform = CGAffineTransform.Scale(transform, 1.0f, -1.0f);
            break;

        case UIImageOrientation.Left:
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Width);
            transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.LeftMirrored :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(imageSize.Height, imageSize.Width);
            transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
            transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.Right :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(imageSize.Height, 0.0f);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.RightMirrored :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeScale(-1.0f, 1.0f);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
            break;

        default :
            break;
    }

    UIGraphics.BeginImageContext(bounds.Size);
    var context = UIGraphics.GetCurrentContext();

    if (orient == UIImageOrientation.Right || orient == UIImageOrientation.Left) {
        context.ScaleCTM(-scaleRatio, scaleRatio);
        context.TranslateCTM(-height, 0);
    } else {
        context.ScaleCTM(scaleRatio, -scaleRatio);
        context.TranslateCTM(0, -height);
    }

    context.ConcatCTM(transform);
    context.DrawImage(new CGRect(0, 0, width, height), imgRef);

    var imageCopy = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();

    return imageCopy;
}

이것은 이것을 가지고 많은 시간을 보낸 후 내 문제를 해결하는 데 도움이되었습니다! Xamarin이 현재 Microsoft 제품이라는 점을 감안할 때 Xamarin에 내장 된 지원이 없다는 것은 믿기지 않습니다.
Sami.C

4

비슷한 문제가 있었지만 Swift를 사용했기 때문에이 질문을 받았습니다. 다른 Swift 개발자에게 도움이 된 답변에 연결하고 싶었습니다. https://stackoverflow.com/a/26676578/3904581

다음은 문제를 효율적으로 수정하는 Swift 스 니펫입니다.

let orientedImage = UIImage(CGImage: initialImage.CGImage, scale: 1, orientation: initialImage.imageOrientation)!

매우 간단합니다. 코드 한 줄. 문제 해결됨.


이것은 나를 위해 작동하지 않았
Leon


0

Swift 3 용으로 빠르게 리팩토링 됨 (누군가 테스트하고 모든 것이 제대로 작동하는지 확인할 수 있습니까?) :

static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage

    let width = CGFloat(imgRef!.width)
    let height = CGFloat(imgRef!.height)

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if width > maxResolution || height > maxResolution {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: imgRef!.width, height: imgRef!.height)

    switch imageSource.imageOrientation {
    case .up :
        transform = CGAffineTransform.identity

    case .upMirrored :
        transform = CGAffineTransform(translationX: imageSize.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)

    case .down :
        transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height)
        transform = transform.rotated(by: CGFloat.pi)

    case .downMirrored :
        transform = CGAffineTransform(translationX: 0, y: imageSize.height)
        transform = transform.scaledBy(x: 1, y: -1)

    case .left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: 0, y: imageSize.width)
        transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0)

    case .leftMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width)
        transform = transform.scaledBy(x: -1, y: 1)
        transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0)

    case .right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: imageSize.height, y: 0)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    case .rightMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(scaleX: -1, y: 1)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()

    if orient == .right || orient == .left {

        context!.scaleBy(x: -scaleRatio, y: scaleRatio)
        context!.translateBy(x: -height, y: 0)
    } else {
        context!.scaleBy(x: scaleRatio, y: -scaleRatio)
        context!.translateBy(x: 0, y: -height)
    }

    context!.concatenate(transform)
    context!.draw(imgRef!, in: CGRect(x: 0, y: 0, width: width, height: height))

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageCopy!
}

0

Dilip의 멋진 답변의 Swift3 버전입니다.

func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage!;

    let width = CGFloat(imgRef.width);
    let height = CGFloat(imgRef.height);

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {
        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: width, height: height)


    switch(imageSource.imageOrientation) {
        case .up :
            transform = CGAffineTransform.identity

        case .upMirrored :
            transform = CGAffineTransform(translationX: imageSize.width, y: 0.0);
            transform = transform.scaledBy(x: -1, y: 1);

        case .down :
            transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height);
            transform = transform.rotated(by: CGFloat(Double.pi));

        case .downMirrored :
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.height);
            transform = transform.scaledBy(x: 1, y: -1);

        case .left :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.width);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .leftMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width);
            transform = transform.scaledBy(x: -1, y: 1);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .right :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: 0.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);

        case .rightMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(scaleX: -1.0, y: 1.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);
    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()!

    if orient == .right || orient == .left {
        context.scaleBy(x: -scaleRatio, y: scaleRatio);
        context.translateBy(x: -height, y: 0);
    } else {
        context.scaleBy(x: scaleRatio, y: -scaleRatio);
        context.translateBy(x: 0, y: -height);
    }

    context.concatenate(transform);
    context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy!;
}

-3

이미지 형식을 .jpeg로 변경해보십시오. 이것은 나를 위해 일했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.