iOS: изображение поворачивается на 90 gradleусов после сохранения в виде данных представления PNG

Я достаточно исследовал этот процесс, но не смог его исправить. После съемки с камеры, пока у меня есть изображение, хранящееся как UIImage, это нормально, но как только я сохранил это изображение в качестве представления PNG, его можно поворачивать на 90 gradleусов.

Ниже приводится мой код и все, что я пробовал:

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

Здесь функции fixOrientation и scaleAndRotateImage берутся здесь и здесь соответственно. Они отлично работают и поворачивают изображение, когда я применяю их в UIImage, но не работают, если я сохраняю изображение как представление PNG и применяю их.

Пожалуйста, обратитесь к следующему рисунку после выполнения следующих функций:

Первая фотография оригинальная, вторая сохранена, а третья и четвертая после применения функции фиксации и масштабирования и защиты на сохраненном изображении

    Начиная с iOS 4.0, когда камера берет фотографию, она не поворачивает ее перед сохранением, это

    просто устанавливает флаг вращения в EXIF-данных JPEG. Если вы сохраняете UIImage как JPEG, это

    установит флаг вращения. ПНГ не поддерживают флаг вращения, поэтому, если вы сохраните UIImage как

    PNG, он будет повернут неправильно и не будет установлен флаг для его исправления. Так что если вы хотите PNG

    изображения, вы должны повернуть их самостоятельно, для этого проверьте эту ссылку .

    Свифт 3.1 версии расширения UIImage, опубликованной Рао:

     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 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() 

    Я нашел следующие советы очень полезными:

    1. Естественный выход – пейзаж

    2. .width / .height ARE зависит от .imageOrientation

    3 используйте короткие измерения, а не .width


    (1) «естественный» выход камеры для неподвижных изображений. 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); 

    вы увидите, что обмен .hight и .width, даже несмотря на то, что реальные пиксели являются ландшафтными.


    (3) просто используя «короткую величину», а не ширину, часто можно решить многие проблемы

    Я нашел это невероятно полезным. Скажем, вы хотите, возможно, верхний квадрат изображения:

     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) не является лекарством, но очень часто решает все проблемы.

    Надеюсь, что это поможет кому-то сэкономить время.

    Я нашел здесь этот код, который фактически исправил его для меня. Для моего приложения я сделал снимок и сохранил его, и каждый раз, когда я его загружал, у него было бы раздражающее rotation (я посмотрел вверх, и это, по-видимому, что-то связано с EXIF ​​и тем, как iPhone берет и хранит изображения). Этот код исправил это для меня. Я должен сказать, что он был первоначально дополнением к classу / расширению / категории (вы можете найти оригинал по ссылке. Я использовал его как ниже, как простой метод, так как я действительно не хотел делать целое class или категория только для этого. Я использовал только портрет, но я думаю, что код работает для любой ориентации. Я не уверен, хотя

    Повторите, вот код:

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

    Я не уверен, насколько это полезно для вас, но я надеюсь, что это помогло 🙂

    Попробуйте это, вы можете использовать

     NSData *somenewImageData = UIImageJPEGRepresentation(newimg,1.0); 

    вместо

     NSData *somenewImageData = UIImagePNGRepresentation(newimg); 

    Pls Попробуйте следующий код

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

    Я ссылаюсь на следующую ссылку, ищите более подробную информацию

    С наилучшими пожеланиями 🙂

    Попробуйте этот код:

     NSData *imageData = UIImageJPEGRepresentation(delegate.originalPhoto,100); 
    Давайте будем гением компьютера.