Подтвердить что ты не робот

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

Я исследовал достаточно, чтобы получить эту работу, но не смог ее исправить. После съемки с камеры, пока у меня есть изображение, хранящееся как 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];
}

Здесь функции 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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

Версия расширения 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.up был переименован в UIImage.Orientation.up

Ответ 3

Swift 4.2

Добавьте следующее как расширение UIImage,

extension UIImage {
    func fixOrientation() -> UIImage? {
        if self.imageOrientation == UIImage.Orientation.up {
            return self
        }

        UIGraphicsBeginImageContext(self.size)
        self.draw(in: CGRect(origin: .zero, size: self.size))
        let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return normalizedImage
    }
}

Пример использования:

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

Ответ 4

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

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

2..width/.height ARE зависит от .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) просто используя "короткую размерность", а не ширину, часто может решить многие проблемы

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

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

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

Ответ 5

Я нашел этот код здесь, который фактически исправил его для меня. Для моего приложения я сделал снимок и сохранил его, и каждый раз, когда я его загружал, у него было бы раздражающее вращение (я посмотрел вверх, и это, по-видимому, что-то связано с 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;
}

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

Ответ 6

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

NSData *somenewImageData = UIImageJPEGRepresentation(newimg,1.0);

вместо

NSData *somenewImageData = UIImagePNGRepresentation(newimg);

Ответ 7

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

Я ссылаюсь на следующую ссылку, ища более detail

С наилучшими пожеланиями: -)

Ответ 8

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

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