iOS PNG Obraz obrócony o 90 stopni
W mojej aplikacji na iOS, którą piszę, zajmuję się PNGs, ponieważ zajmuję się kanałem alfa. Z jakiegoś powodu mogę załadować PNG do mojej imageView
, ale kiedy przychodzi czas, aby albo skopiować obraz z mojej aplikacji (na planszę) lub zapisać obraz do mojej rolki aparatu, obraz obraca się o 90 stopni.
Szukałem wszędzie na ten temat i jedną z rzeczy, których się nauczyłem, jest to, że gdybym używał JPEG, nie miałbym tego problemu( brzmi), ze względu na informacje EXIF.
Moja aplikacja ma pełną funkcję kopiowania/wklejania, a oto kicker (napiszę to w krokach, aby było łatwiej śledzić):
- przejdź do rolki mojego aparatu i Skopiuj obraz
- wejdź do mojej aplikacji i naciśnij "Wklej", obraz pasty dobrze, I mogę to zrobić cały dzień
- Kliknij zaimplementowaną funkcję kopiowania, a następnie kliknij "Wklej", a obraz zostanie wklejony, ale zostanie obrócony.
Jestem w 100% pewien, że mój kod do kopiowania i wklejania nie jest tym, co jest tutaj nie tak, ponieważ jeśli wrócę do Krok 2 powyżej i kliknij "Zapisz", zdjęcie zapisuje się w mojej bibliotece, ale jest obracane o 90 stopni!
Jeszcze bardziej dziwne jest to, że wydaje się, że działa dobrze z obrazami pobranymi z internetu, ale jest bardzo hit lub miss z obrazami, które ręcznie zrobiłem telefonem. Niektóre działają, inne nie...
Czy ktoś ma jakieś przemyślenia na ten temat? Jakieś możliwości pracy w okolicy, które mogę wykorzystać? Jestem całkiem pewien, że kod działa dla około 75% moich obrazów. Mogę wysłać kod po ale proszę.6 answers
Dla tych, którzy chcą szybkiego rozwiązania, Utwórz rozszerzenie UIImage i dodaj następującą metodę:
func correctlyOrientedImage() -> UIImage {
if self.imageOrientation == .up {
return self
}
UIGraphicsBeginImageContextWithOptions(size, false, scale)
draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage ?? self;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 12:43:08
Jeśli masz problemy z istniejącą właściwością image imageOrientation
, możesz skonstruować identyczny obraz o innej orientacji w następujący sposób:
CGImageRef imageRef = [sourceImage CGImage];
UIImage *rotatedImage = [UIImage imageWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationUp];
Być może będziesz musiał poeksperymentować z tym, jaką orientację ustawić na obrazach zastępczych, ewentualnie przełączając się na podstawie orientacji, od której zacząłeś.
Miej również oko na zużycie pamięci. Aplikacje fotograficzne często się kończą, a to podwoi ilość miejsca na zdjęcie, dopóki nie udostępnisz źródła obraz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-25 02:46:32
Zajęło to kilka dni, ale w końcu rozgryzłem to dzięki odpowiedzi, którą napisał @Dondragmer. Ale pomyślałem, że opublikuję moje pełne rozwiązanie.
Więc w zasadzie musiałem napisać metodę inteligentnego automatycznego obracania moich obrazów. Minusem jest to, że muszę wywoływać tę metodę wszędzie w całym moim kodzie i jest to rodzaj intensywnego procesora, szczególnie podczas pracy na urządzeniach mobilnych, ale plusem jest to, że mogę robić obrazy, kopiować obrazy, wklejać obrazy i zapisywać obrazy, a wszystkie się obracają jak należy. Oto kod, którego użyłem (metoda nie jest jeszcze w 100% kompletna, nadal trzeba edytować wycieki pamięci i co nie).
W końcu dowiedziałem się, że po raz pierwszy obraz został wstawiony do mojej aplikacji (czy to ze względu na użytkownika naciśnięcie "take image", "wklej obraz", lub "wybierz obraz", z jakiegoś powodu wstawić tylko dobrze bez automatycznego obracania. W tym momencie zapisałem wartość rotacji w zmiennej globalnej o nazwie imageOrientationWhenAddedToScreen
. To ułatwiło mi życie, ponieważ kiedy nadszedł czas, aby manipulować obrazem i zapisać obraz z programu, po prostu sprawdziłem tę buforowaną zmienną globalną i określiłem, Czy muszę prawidłowo obrócić obraz.
- (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;
}
Nadal nie jestem w 100% pewien, dlaczego Apple ma takie dziwne zachowanie rotacji obrazu (spróbuj tego... Weź telefon i obróć go do góry nogami i zrób zdjęcie, zauważysz, że ostateczne zdjęcie okazuje się prawą stroną do góry - być może dlatego Apple ma tego typu funkcjonalność?).
I know I spędziłem dużo czasu na wymyślaniu tego, więc mam nadzieję, że pomoże to innym ludziom!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-19 16:07:59
To "dziwne zachowanie rotacji" nie jest wcale takie dziwne. Jest inteligentny, a przez inteligentny mam na myśli wydajną pamięć. Po obróceniu urządzenia z systemem iOS sprzęt kamery obraca się wraz z nim. Po zrobieniu zdjęcia to zdjęcie zostanie zrobione jednak aparat jest zorientowany. UIImage jest w stanie używać tych surowych danych obrazu bez kopiowania, po prostu śledząc orientację, w której powinien się znajdować. Kiedy używasz UIImagePNGRepresentation()
tracisz te dane orientacyjne i otrzymujesz PNG podstawowego obrazu jako zostało zrobione przez kamerę. Aby to naprawić, zamiast obracać, możesz powiedzieć oryginalnemu obrazowi, aby narysował się w nowym kontekście i uzyskać odpowiednio zorientowany UIImage
z tego kontekstu.
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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-05 19:35:13
Oto jeszcze jeden sposób, aby to osiągnąć:
@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)
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-13 10:38:32
Możesz użyć Image I / O, aby zapisać obraz PNG do pliku (lub NSMutableData
) w odniesieniu do orientacji obrazu. W poniższym przykładzie zapisuję obraz PNG do pliku 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:
jest metodą UIImage
kategorii.
+ (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;
}
Możesz alternatywnie zapisać obrazek do NSData
używając CGImageDestinationCreateWithData
i przekazać NSMutableData
zamiast NSURL
w CGImageDestinationCreateWithURL
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-17 10:30:12