IOS PNG Изображение повернуто на 90 градусов
В моем приложении iOS я пишу, я имею дело с PNG, потому что я имею дело с альфа-каналом. По какой-то причине я могу загружать PNG в мой imageView
просто отлично, но когда приходит время либо скопировать изображение из моего приложения (на PasteBoard), либо сохранить изображение в рулоне камеры, изображение поворачивается на 90 градусов,
Я искал всюду на этом, и одна из вещей, которые я узнал, - это то, что если бы я использовал JPEG, у меня не было бы этой проблемы (это звучит) из-за информации EXIF.
Мое приложение имеет полную функциональность для копирования/вставки, а вот кикер (я напишу это пошагово, чтобы было легче следовать):
- Перейдите к рулону камеры и скопируйте изображение.
- Зайдите в мое приложение и нажмите "Вставить", изображение вставляется в порядке, и я могу сделать это весь день.
- Выберите функцию копирования, которую я выполнил, а затем нажмите "Вставить", и изображение вставляется, но повернуто.
Я на 100% уверен, что мой код для копирования и вставки не является тем, что здесь неправильно, потому что, если я вернусь к шагу 2 выше и нажмите "сохранить", фотография будет сохранена в моей библиотеке, но она будет повернута на 90 градусов!
Что еще более странно, так это то, что он отлично работает с изображениями, загруженными из Интернета, но очень сильно ударил или пропустил изображения, которые я вручную взял с телефоном. Некоторые из них работают, некоторые из них не...
Есть ли у кого-нибудь мысли об этом? Любая возможная работа, которую я могу использовать? Я довольно уверен в коде, потому что он работает примерно на 75% моих изображений. Я могу отправить код по запросу, хотя.
Ответы
Ответ 1
Взял несколько дней, но я, наконец, понял это благодаря ответу @Dondragmer. Но я решил, что отправлю свое полное решение.
Так что в основном мне приходилось писать метод, чтобы интеллектуально автоматически поворачивать мои изображения. Недостатком является то, что я должен называть этот метод всюду по всему моему коду, и он очень интенсивный, особенно при работе на мобильных устройствах, но плюс сторона заключается в том, что я могу снимать изображения, копировать изображения, вставлять изображения и сохранять изображения и все они вращаются должным образом. Здесь код, который я использовал (метод не на 100% завершен, все равно нужно отредактировать утечки памяти, а что нет).
В итоге я узнал, что в первый раз изображение было вставлено в мое приложение (будь то из-за нажатия пользователем "взять изображение", "вставить изображение" или "выбрать изображение", по какой-то причине он вставляет только отлично, без автоматического поворота. В этот момент я сохранил все значения вращения в глобальной переменной под названием imageOrientationWhenAddedToScreen
. Это облегчило мою жизнь, потому что, когда пришло время манипулировать изображением и сохранить изображение из программы, я просто проверил эту глобальную переменную cached и определил, нужно ли мне правильно поворачивать изображение.
- (UIImage*) rotateImageAppropriately:(UIImage*) imageToRotate {
//This method will properly rotate our image, we need to make sure that
//We call this method everywhere pretty much...
CGImageRef imageRef = [imageToRotate CGImage];
UIImage* properlyRotatedImage;
if (imageOrientationWhenAddedToScreen == 0) {
//Don't rotate the image
properlyRotatedImage = imageToRotate;
} else if (imageOrientationWhenAddedToScreen == 3) {
//We need to rotate the image back to a 3
properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:3];
} else if (imageOrientationWhenAddedToScreen == 1) {
//We need to rotate the image back to a 1
properlyRotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:1];
}
return properlyRotatedImage;
}
Я до сих пор не уверен на 100%, почему у Apple есть это странное поведение в обращении с картинками (попробуйте это... Возьмите свой телефон и переверните его вверх дном и сделайте снимок, вы заметите, что окончательное изображение получается справа вверх - возможно, именно поэтому у Apple есть такая функциональность?).
Я знаю, что потратил много времени на это, поэтому надеюсь, что это поможет другим людям!
Ответ 2
Для тех, кто хочет решение Swift, создайте расширение UIImage и добавьте следующий метод:
func correctlyOrientedImage() -> 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))
var normalizedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage;
}
Ответ 3
Если у вас возникли проблемы из-за существующего образа imageOrientation
, вы можете построить другое идентичное изображение с другой ориентацией, например:
CGImageRef imageRef = [sourceImage CGImage];
UIImage *rotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUp];
Вам может потребоваться поэкспериментировать с какой именно ориентацией для установки на ваших сменных изображениях, возможно, переключившись на основе ориентации, с которой вы начали.
Также следите за использованием вашей памяти. Приложения для фотосъемки часто заканчиваются, и это будет вдвое больше вашего хранилища на изображение, пока вы не отпустите исходное изображение.
Ответ 4
Такое поведение "странного вращения" действительно не так уж и странно. Это разумно, и по умному я имею в виду эффективность памяти. При повороте устройства iOS аппаратное обеспечение камеры вращается вместе с ним. Когда вы делаете снимок, изображение будет записано, однако камера ориентирована. UIImage может использовать эти необработанные данные изображения без копирования, просто отслеживая ориентацию, в которой он должен находиться. Когда вы используете UIImagePNGRepresentation()
, вы теряете эти данные ориентации и получить PNG основного изображения, как это было сделано камерой. Чтобы исправить это вместо поворота, вы можете указать исходному изображению, чтобы привлечь себя к новому контексту и получить правильно ориентированный UIImage
из этого контекста.
UIImage *image = ...;
//Have the image draw itself in the correct orientation if necessary
if(!(image.imageOrientation == UIImageOrientationUp ||
image.imageOrientation == UIImageOrientationUpMirrored))
{
CGSize imgsize = image.size;
UIGraphicsBeginImageContext(imgsize);
[image drawInRect:CGRectMake(0.0, 0.0, imgsize.width, imgsize.height)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
NSData *png = UIImagePNGRepresentation(image);
Ответ 5
Вот еще один способ добиться этого:
@IBAction func rightRotateAction(sender: AnyObject) {
let imgToRotate = CIImage(CGImage: sourceImageView.image?.CGImage)
let transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
let rotatedImage = imgToRotate.imageByApplyingTransform(transform)
let extent = rotatedImage.extent()
let contex = CIContext(options: [kCIContextUseSoftwareRenderer: false])
let cgImage = contex.createCGImage(rotatedImage, fromRect: extent)
adjustedImage = UIImage(CGImage: cgImage)!
UIView.transitionWithView(sourceImageView, duration: 0.5, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
self.sourceImageView.image = self.adjustedImage
}, completion: nil)
}
Ответ 6
Вы можете использовать Image I/O для сохранения изображения PNG в файл (или NSMutableData
) относительно ориентации изображения. В приведенном ниже примере я сохраняю PNG-изображение в файле path
.
- (BOOL)savePngFile:(UIImage *)image toPath:(NSString *)path {
NSData *data = UIImagePNGRepresentation(image);
int exifOrientation = [UIImage cc_iOSOrientationToExifOrientation:image.imageOrientation];
NSDictionary *metadata = @{(__bridge id)kCGImagePropertyOrientation:@(exifOrientation)};
NSURL *url = [NSURL fileURLWithPath:path];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
if (!source) {
return NO;
}
CFStringRef UTI = CGImageSourceGetType(source);
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)url, UTI, 1, NULL);
if (!destination) {
CFRelease(source);
return NO;
}
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)metadata);
BOOL success = CGImageDestinationFinalize(destination);
CFRelease(destination);
CFRelease(source);
return success;
}
cc_iOSOrientationToExifOrientation:
- метод категории UIImage
.
+ (int)cc_iOSOrientationToExifOrientation:(UIImageOrientation)iOSOrientation {
int exifOrientation = -1;
switch (iOSOrientation) {
case UIImageOrientationUp:
exifOrientation = 1;
break;
case UIImageOrientationDown:
exifOrientation = 3;
break;
case UIImageOrientationLeft:
exifOrientation = 8;
break;
case UIImageOrientationRight:
exifOrientation = 6;
break;
case UIImageOrientationUpMirrored:
exifOrientation = 2;
break;
case UIImageOrientationDownMirrored:
exifOrientation = 4;
break;
case UIImageOrientationLeftMirrored:
exifOrientation = 5;
break;
case UIImageOrientationRightMirrored:
exifOrientation = 7;
break;
default:
exifOrientation = -1;
}
return exifOrientation;
}
Вы также можете сохранить изображение NSData
с помощью CGImageDestinationCreateWithData
и передать NSMutableData
вместо NSURL
в CGImageDestinationCreateWithURL
.