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の欠陥であると数人の人が提案しました。

(...まだ迷っていない場合...注2:横向きの写真を撮ると、インターネットから撮った写真と同じように、すべてが完璧に機能しているように見えます)

編集:

ここに、いくつかの画像とシナリオが実際にどのように見えるかを示します。これまでのコメントに基づくと、この奇妙な動作は単なるiPhoneの動作ではないようです。

これは私が携帯電話で撮った写真の写真です(正しい向きに注意してください)。写真をスナップしたときの携帯電話とまったく同じように表示されます。

iPhoneで実際に撮影した写真

自分にメールした後のGmailの画像は次のとおりです(Gmailで適切に処理されているようです)。

Gmailに表示される写真

ウィンドウにサムネイルとして表示される画像は次のとおりです(適切に処理されているようには見えません)。

Windowsサムネイル

Windowsフォトビューアーで開いたときの実際の画像は次のとおりです(まだ適切に処理されていません)。

Windowsフォトビューアーのバージョン

この質問に対するすべてのコメントの後に、私が考えているのはこれです... iPhoneは画像を取得し、「これを適切に表示するには、90度回転させる必要があります」と言います。この情報はEXIFデータに含まれます。(なぜデフォルトでは真っ直ぐな垂直ではなく90度回転する必要があるのか​​、私にはわかりません)。ここから、GmailはそのEXIFデータを読み取って分析し、適切に表示するのに十分スマートです。ただし、Windowsは、EXIFデータを読み取るほどスマートではないため、画像が正しく表示されません。私の仮定は正しいですか?


興味深い...それが本当なら、撮影された画像が直角に設定されるのはなぜですか?私はこれがiPhoneの欠陥ではないことを知っています。私が友人(BlackBerryを持っている)が画像を撮ってMMSがそれを私に受け取ったときの同様の動作に気付いたからです。
Boeckm

カメラがメタデータを書き込んで90度回転させることを確認します。一部のOSはそのメタデータを読み取り、残りはそれを行いません。
HarshIT

かなり良い読み物です(以下の@Hadleyの回答を参照してください-以前はコメントでした)。したがって、私のアプリは明らかに、EXIFデータを含む画像だけでなく、EXIFデータを含まない画像も処理できるほどスマートである必要があります...写真を裏返しにして写真を撮ると、方向フラグそれは90度回転する必要があると言いますか?
Boeckm

写真モードをポートレートに設定し、カメラを直角に回転していないか、ランドスケープモードが設定されており、カメラが画像を直角の位置でキャプチャした場合、センサーは自動的に向きを適切な方向に設定します。チェックしてください
HarshIT

1
ほとんどの場合、解決策は、アプリがメタデータを読み取り、画像を回転するか、要件に応じてメタデータを変更する必要があることです。
HarshIT、2012年

回答:


50

私はそれを研究開発し、発見しました。すべての画像ファイルにはメタデータプロパティがあります。メタデータが画像の向きを指定している場合、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 -任意のjpeg画像のメタデータ情報/オンライン/


1
うわー!EXIFデータにそのような多くの情報があるとは知りませんでした! regex.info/exif.cgiは素晴らしいサイトです!私は確かに今夜このサイトで画像で遊んでいます。私はすべてのシナリオをテストする必要があります。画像はまっすぐ撮り、インターネットから撮った画像、回転させて撮った画像などです。ありがとうございます。
Boeckm

最初のexifリンクが壊れて、2番目のリンクがexif.regex.info/exif.cgiに更新されました回答を編集しようとしましたが、@ cj-dennisが何らかの理由で拒否しました。
ライアン

55

Cameraから画像を取得するときに同じ問題が発生したため、次のコードを追加して修正しました。ここからメソッド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
わぁ…はは!それは非常にうまくいきました!上記のコメントでコードを使用しました。私の質問には2つのすばらしい答えが得られました。それは私があまりにも多くの質問をしたことを意味していると思います...ありがとうございます。いくつかの詳細なテストを行う予定ですが、これまでのところ、向きの問題は、垂直方向および水平方向に撮影した写真でうまく機能します。
Boeckm、2012年

3
私はあなたのメソッドの一部が欠けていると思いますが、それでもリンクは私が残りを解決し、最終的に私の画像クロッピングビューを適切に機能させるのに十分でしたので、:)
Vic Smith

私はそれが助けてくれてうれしいです.. :)
Dilip Rajkumar

このコードブロックは、元の画像の外観を維持しますが、向きを上に変更しますか?
Junchao Gu

18

Dilipの優れた答えのクイックコピー/貼り付けSwift翻訳。

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レシオ=幅/高さ」とは何ですか。のために使用?その中で比率を使用している場所はどこにもありません{}
Pengzhi Zhou

18

今回の私の質問は、なぜこれが起こっているのですか?Appleが画像を回転させるのはなぜですか?

これに対する答えは非常に簡単です。Appleは画像を回転させていません。そこに混乱があります。

CCDカメラは回転しないので、常に横向きモードで写真を撮っています。

Appleは、画像を回転させるために常に時間を費やすのではなく、メガバイトのデータをシャッフルするのではなく、非常に賢明なことを行いました。写真の撮影方法をタグ付けするだけです。

OpenGLは非常に簡単に翻訳を行うため、データが変更されることはありません。

したがって、向きのメタデータです。

これは、トリミングやサイズ変更などを行う場合に問題になります。ただし、何が起こっているかがわかったら、マトリックスを定義するだけですべてがうまくいきます。


1
この説明をありがとうございます。一度考えれば常識だが、他のグーグルの結果ではそれを説明できなかった。
Dakine83 2016年

16

ディリップの答えの安全性チェック付きの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)ストレージとして変数を作成せずに行うこともできます。
アルマスサパルガリ2017

拡大縮小した後、画像の下部に白い線が表示されるという問題が時々ありました。これは、CGFloatが十分に正確ではないように見えるためです。私はこれを固定bounds.size.height.round()し、bounds.size.width.round()
ndreisg

13

iPhone / iPadによって生成された画像はすべて、実際の方向を指定するEXIF方向タグ(Exif.Image.Orientation)を使用して、Landscape Leftとして保存されます。

次の値があります。1:左に横向き6:通常の縦向き3:右向きに横向き4:逆向きの縦向き

IOSでは、EXIF情報が適切に読み取られ、画像は撮影時と同じように表示されます。しかし、Windowsでは、EXIF情報は使用されません。

これらの画像のいずれかをGIMPで開くと、画像に回転情報があると表示されます。


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製品であることを考えると、これに対する組み込みのサポートがないことは信じられません。
Sami.C 2018年

4

私は同様の問題を抱えていたが、Swiftを使用していたため、この質問に出くわしました。他のSwift開発者のために私のために働いた答えにリンクしたかっただけです:https//stackoverflow.com/a/26676578/3904581

問題を効率的に修正するSwiftスニペットは次のとおりです。

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

超シンプル。1行のコード。問題が解決しました。


これは私にとってはうまくいきませんでした、私はこのソリューションを使用しました:stackoverflow.com/a/27775741/945247
Leon

0

私はあなたの問題が何であるかを正確に知っています。あなたはあらゆる意味で奇妙なUIImagePickerを使用しています。カメラにAVFoundationを使用して、向きだけでなく品質にも柔軟性を与えることをお勧めします。AVCaptureSessionを使用します。ここでコードを取得できます。AVFoundationを使用して撮影した写真をフォトアルバムに保存する方法は?


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

これがディリップの素晴らしい答えの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!;
}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.