web-dev-qa-db-ja.com

iOS:PNG表現データとして保存した後、画像が90度回転します

私はこれを機能させるのに十分な研究をしましたが、修正することはできません。画像をUIImageとして保存している限りカメラから写真を撮った後は問題ありませんが、この画像をPNG表現として保存するとすぐに、90度回転します。

以下は私のコードと私が試したすべてのものです:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{
    NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];

    if([mediaType isEqualToString:(NSString*)kUTTypeImage]) 
    {
        AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
        delegate.originalPhoto  = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
        NSLog(@"Saving photo");
        [self saveImage];
        NSLog(@"Fixing orientation");
        delegate.fixOrientationPhoto  = [self fixOrientation:[UIImage imageWithContentsOfFile:[delegate filePath:imageName]]];      
        NSLog(@"Scaling photo");
        delegate.scaledAndRotatedPhoto  =  [self scaleAndRotateImage:[UIImage imageWithContentsOfFile:[delegate filePath:imageName]]];
    }
    [picker dismissModalViewControllerAnimated:YES];
    [picker release];
}


- (void)saveImage
{
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSData *imageData = UIImagePNGRepresentation(delegate.originalPhoto);
    [imageData writeToFile:[delegate filePath:imageName] atomically:YES];
}

ここでは、それぞれ here および here から取得したfixOrientationおよびscaleAndRotateImage関数。 UIImageに適用すると正常に動作し、画像を回転しますが、画像をPNG表現として保存して適用すると動作しません。

上記の機能を実行した後、次の図を参照してください。

The first photo is original, second is saved, and third and fourth after applying fixorientation and scaleandrotate functions on saved image

37
applefreak

IOS 4.0以降、カメラが写真を撮るとき、保存する前に写真を回転させません。

jPEGのEXIFデータに回転フラグを設定するだけです。UIImageをJPEGとして保存すると、

回転フラグを設定します。PNGは回転フラグをサポートしていないため、UIImageを

PNG、それは間違って回転し、それを修正するためのフラグが設定されていません。したがって、PNGが必要な場合

画像を自分で回転させる必要があります。そのためには、この link をチェックしてください。

68
Mudit Bajpai

Raoが投稿したUIImage拡張機能のSwift 3.1バージョン:

extension UIImage {
    func fixOrientation() -> UIImage {
        if self.imageOrientation == UIImageOrientation.up {
            return self
        }
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        if let normalizedImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            return normalizedImage
        } else {
            return self
        }
    }
}

使用法:

let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()

Swift 4/5:

UIImageOrientation.upUIImage.Orientation.upに名前が変更されました

26
Andreas

Swift 2.1

UIImage拡張機能として次を追加します。

extension UIImage {
   func fixOrientation() -> UIImage {
        if self.imageOrientation == UIImageOrientation.Up {
            return self
        }

        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        self.drawInRect(CGRectMake(0, 0, self.size.width, self.size.height))
        let normalizedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return normalizedImage;
    }
}

使用例:

let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()
19
Rao

次のヒントが非常に役立つことがわかりました。

1.自然出力はランドスケープ

2. .width/.heightは.imageOrientationの影響を受けます

3 .widthではなく短い寸法を使用する


(1)静止画用のカメラの「自然な」出力IS LANDSCAPE。

これは直感に反します。 UIImagePickerControllerなどが提供する唯一の方法はポートレートです。ただし、「通常の」ポートレートカメラを使用すると、UIImageOrientationRightが「通常の」方向になります。

(私がこれを覚えている方法-ビデオの自然な出力は(もちろん)風景です;そのため、iPhoneはすべてポートレートについてですが、静止画は同じです。)


(2).widthと.height 実際に.imageOrientation !!!!!!!!!の影響を受けます

必ずこれを行い、iPhoneで両方の方法で試してください。

NSLog(@"fromImage.imageOrientation is %d", fromImage.imageOrientation);
NSLog(@"fromImage.size.width  %f   fromImage.size.height  %f",
            fromImage.size.width, fromImage.size.height);

実際のピクセルが横向きであっても、.heightと.widthのスワップが表示されます。


(3).widthではなく単に「短い寸法」を使用する多くの問題を解決できることが多い

これは非常に役立つことがわかりました。画像の一番上の正方形が必要だとします:

CGRect topRectOfOriginal = CGRectMake(0,0, im.size.width,im.size.width);

実際には機能しませんが、カメラが(「本当に」)横向きに保持されていると、画像がつぶれてしまいます。

ただし、非常に単純にこれを行う場合

float shortDimension = fminf(im.size.width, im.size.height);
CGRect topRectOfOriginal = CGRectMake(0,0, shortDimension,shortDimension);

次に、「すべてが修正されます」と実際に"心配する必要はありません"方向フラグ。繰り返しますが、ポイント(3)は万能薬ではありませんが、多くの場合すべての問題を解決します。

誰かが時間を節約するのに役立つことを願っています。

6
Fattie

これを試して、あなたが使用することができます

NSData *somenewImageData = UIImageJPEGRepresentation(newimg,1.0);

の代わりに

NSData *somenewImageData = UIImagePNGRepresentation(newimg);
3
vijay

このコードを見つけました here 、実際に修正してくれました。私のアプリでは、写真を撮って保存し、ロードするたびに迷惑な回転が表示されました(見上げると、どうやらEXIFとiPhoneが画像を取得して保存する方法と関係があるようです)。このコードは私のためにそれを修正しました。私は言わなければならない、それはもともとクラス/拡張機能/カテゴリへの追加としてでした(あなたはリンクから元を見つけることができます。私は本当に全体を作りたくなかったので、簡単な方法として以下のようにそれを使用しましたこれだけのクラスまたはカテゴリです。ポートレートのみを使用しましたが、コードはどの向きでも機能すると思います。

ここにコードがあります:

- (UIImage *)fixOrientationForImage:(UIImage*)neededImage {

    // No-op if the orientation is already correct
    if (neededImage.imageOrientation == UIImageOrientationUp) return neededImage;

    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    CGAffineTransform transform = CGAffineTransformIdentity;

    switch (neededImage.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, neededImage.size.width, neededImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, neededImage.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;

        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, neededImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationUpMirrored:
            break;
    }

    switch (neededImage.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, neededImage.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;

        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, neededImage.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationDown:
        case UIImageOrientationLeft:
        case UIImageOrientationRight:
            break;
    }

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, neededImage.size.width, neededImage.size.height,
                                             CGImageGetBitsPerComponent(neededImage.CGImage), 0,
                                             CGImageGetColorSpace(neededImage.CGImage),
                                             CGImageGetBitmapInfo(neededImage.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (neededImage.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,neededImage.size.height,neededImage.size.width), neededImage.CGImage);
            break;

        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,neededImage.size.width,neededImage.size.height), neededImage.CGImage);
            break;
    }

    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}

これがあなたにとってどれほど役立つかはわかりませんが、役に立てば幸いです:)

2
Septronic

次のコードを試してください

UIImage *sourceImage = ... // Our image
CGRect selectionRect = CGRectMake(100.0, 100.0, 300.0, 400.0);
CGImageRef resultImageRef = CGImageCreateWithImageInRect(sourceImage.CGImage,
selectionRect);
UIImage *resultImage = [[UIImage alloc] initWithCGImage:resultImageRef];

そして

CGRect TransformCGRectForUIImageOrientation(CGRect source, UIImageOrientation orientation, CGSize imageSize) {
switch (orientation) {
case UIImageOrientationLeft: { // EXIF #8
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI_2);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationDown: { // EXIF #3
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationRight: { // EXIF #6
  CGAffineTransform txTranslate = CGAffineTransformMakeTranslation(0.0, imageSize.width);
  CGAffineTransform txCompound = CGAffineTransformRotate(txTranslate,M_PI + M_PI_2);
  return CGRectApplyAffineTransform(source, txCompound);
}
case UIImageOrientationUp: // EXIF #1 - do nothing
  default: // EXIF 2,4,5,7 - ignore
  return source;
}
}
  ...
UIImage *sourceImage = ... // Our image
 CGRect selectionRect = CGRectMake(100.0, 100.0, 300.0, 400.0);
CGRect transformedRect = TransformCGRectForUIImageOrientation(selectionRect,  sourceImage.imageOrientation, sourceImage.size);
CGImageRef resultImageRef = CGImageCreateWithImageInRect(sourceImage.CGImage, transformedRect);
UIImage *resultImage = [[UIImage alloc] initWithCGImage:resultImageRef];

私は次のリンクから参照しています-より多くを探しています detail

宜しくお願いします :-)

1
NIKHIL

このコードを試してください:

NSData *imageData = UIImageJPEGRepresentation(delegate.originalPhoto,100);
0
Mubasher