iOS: Imaginea se rotește la 90 de grade după ce a fost salvată ca date de reprezentare PNG

Am cercetat suficient pentru a obține acest lucru, dar nu am reușit să o rezolv. După ce am făcut o fotografie din camera, atâta timp cât am stocat imaginea ca UIImage, este bine, dar de îndată ce am stocat această imagine ca reprezentare PNG, se rotește la 90 de grade.

Urmează codul meu și toate lucrurile pe care le-am încercat:

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

Aici funcțiile fixOrientation și scaleAndRotateImage sunt preluate de la aici și aici respectiv. Ei funcționează bine și rotesc imaginea când le aplic pe UIImage, dar nu funcționează dacă salvez imaginea ca reprezentare PNG și le aplic.

Vă rugăm să faceți următoarea imagine după executarea funcțiilor de mai sus:

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

32
Nu amice. Vă lipiți toate legăturile referitoare la această problemă. Am trecut prin toate!
adăugat autor applefreak, sursa
Anonim, dacă scadează această întrebare, atunci nu ați înțeles întrebarea! Am văzut că aveți această problemă aici - stackoverflow.com/questions/3554244/… :-) Ați rezolvat-o?
adăugat autor applefreak, sursa
Foarte utile: 1. ieșirea naturală este peisaj 2. lățime/vârf ARE afectate de .imageOrientation
adăugat autor Fattie, sursa
adăugat autor Septronic, sursa

8 răspunsuri

Începând cu versiunea iOS 4.0 când aparatul foto face o fotografie, acesta nu îl rotește înainte de salvare

stabilește pur și simplu un steag de rotire în datele EXIF ​​ale JPEG. Dacă salvați un UIImage ca JPEG, acesta

va stabili stegul de rotație.PNG-urile nu acceptă un steg de rotație, deci dacă salvați un UIImage ca

PNG, acesta va fi rotit incorect și nu are un set de pavilion pentru a-l repara. Deci, dacă doriți PNG

imagini trebuie să le rotiți singuri, pentru că verificați acest link .

59
adăugat
Ai avut dreptate. Acest lucru mi-a luat cel puțin 24 de ore pentru a repara!
adăugat autor applefreak, sursa
super mulțumesc de lucru bine.
adăugat autor vijay, sursa
Vă recomandăm să citiți acest răspuns. Mai exact răspunsul de la 'an0' pare a fi cea mai concisă.
adăugat autor Mike Casa, sursa

Versiunea Swift 3.1 a extensiei UIImage postată de Rao:

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

utilizare:

let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()
18
adăugat
Mulțumesc foarte mult !!!
adăugat autor Tà Truhoada, sursa

Pentru Swift 2.1

Adăugați următoarele ca extensie 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;
    }
}

Exemplu de utilizare:

let cameraImage = //image captured from camera
let orientationFixedImage = cameraImage.fixOrientation()
14
adăugat
@ return0 Multumesc! Vă rugăm să luați în considerare ridicarea răspunsului.
adăugat autor Rao, sursa
Probabil cel mai bun răspuns până acum, care nu utilizează combinații de hacking împreună. Foarte frumos.
adăugat autor Munib, sursa
De mare ajutor. Mulțumesc!!
adăugat autor Baylor Mitchell, sursa

Am gasit urmatoarele sfaturi pentru a fi extrem de utile:

1. natural output is landscape

2. lățimea/vârful sunt afectate de

3 utilizați dimensiunea scurtă mai degrabă decât .width


(1) the 'natural' output of the camera for stills IS LANDSCAPE.

acest lucru este contraintuitiv. portretul este singura modalitate oferită de UIImagePickerController etc. Dar veți obține UIImageOrientationRight ca orientare "normală" când folosiți camera portret "normală"

(Modul în care îmi amintesc acest lucru - ieșirea naturală pentru video este (bineînțeles) peisaj, deci fotografiile sunt aceleași - chiar dacă iPhone-ul are totul despre portret.)


(2) .width and .height are indeed affected by the .imageOrientation!!!!!!!!!

Asigurați-vă că faceți acest lucru și încercați în ambele sensuri pe iPhone,

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

veți vedea că schimbarea ".high" și ".width", chiar dacă "pixelii reali sunt peisaj.


(3) simply using the "short dimension" rather than .width, can often solve many problems

Am aflat că acest lucru este incredibil de util. Spuneți că doriți, probabil, pătratul de sus al imaginii:

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

că de fapt nu va funcționa, veți obține o imagine ciudată, atunci când camera este ("într-adevăr") fiind ținută peisaj.

totuși, dacă faceți foarte simplu acest lucru

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

apoi "totul este fix" și de fapt "nu trebuie să vă faceți griji despre stegulețul de orientare. Din nou punctul (3) nu este un remediu, dar foarte des rezolvă toate problemele.

Sper că îi ajută pe cineva să economisească ceva timp.

5
adăugat
mulțumesc @furins!
adăugat autor Fattie, sursa
Presupun că în ultimul exemplu ar trebui să folosiți shortDimension undeva (poate în loc de im.size.width în al doilea rând?)
adăugat autor furins, sursa

Am găsit acest cod aici , care de fapt, a fixat-o pentru mine. Pentru aplicația mea, am făcut o fotografie și l-am salvat și, de fiecare dată când l-am încărcat, mi-ar fi atras rotația enervantă (m-am uitat în sus și se pare că are legătură cu EXIF ​​și modul în care iPhone ia și stochează imagini). Acest cod mi-a fixat-o. Trebuie să spun, a fost inițial ca o adăugare la o clasă/o extensie/categorie (puteți găsi originalul de la link-ul. Am folosit-o ca mai jos ca o simplă metodă, deoarece nu am vrut cu adevărat să fac un întreg clasa sau categoria doar pentru asta.Am folosit doar portret, dar cred că codul funcționează pentru orice orientare.Nu sunt sigur, totuși

Rânduleți, iată codul:

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

Nu sunt sigur cât de util va fi pentru tine, dar sper că a ajutat :)

2
adăugat
Funcționează bine, dar comprimă calitatea imaginii. calitatea imaginii după rotație nu este bună.
adăugat autor L Ananta Prasad, sursa
Multumesc pentru raspuns. Eu folosesc codul în aplicația mea, dar primesc rapoarte de accident, imaginea returnată de la această funcție se distruge într-un fel corupt, se pare că această funcție face scurgeri de memorie de aceea. Aveți aceleași probleme și cum o pot rezolva?
adăugat autor Karen Karapetyan, sursa

Incearca asta, Poți să folosești

NSData *somenewImageData = UIImageJPEGRepresentation(newimg,1.0);

in loc de

NSData *somenewImageData = UIImagePNGRepresentation(newimg);
1
adăugat

Pls Încercați următorul cod

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

Și

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

I have referanced from following link have look for more detail

Toate cele bune :-)

1
adăugat
De unde treceți valoarea "orientării" în "CGRect TransformCGRectForUIImageOrientation (sursa CGRect, orientare UIImageOrientation, CGSize imageSize)
adăugat autor Developer, sursa
Mulțumesc, dar nici nu funcționează. Am folosit CGRect selectionRect = CGRectMake (0, 0, sourceImage.size.width, sourceImage.size.height); pentru a roti imaginea completă dar totuși se pare că este rotit 90 de grade. Rețineți că fac această operație după stocarea imaginii local în dosarul documentelor. Mulțumiri.
adăugat autor applefreak, sursa

Încercați acest cod:

NSData *imageData = UIImageJPEGRepresentation(delegate.originalPhoto,100);
0
adăugat
Acest lucru nu oferă un răspuns la întrebare. Pentru a critica sau a solicita clarificări de la un autor, lăsați un comentariu sub postarea lor - puteți oricând să comentați propriile dvs. postări și, odată ce aveți suficiente reputația veți putea să comenta la orice postare .
adăugat autor ericbn, sursa
problemă de rotație apare când stocați imaginea ca PNGRpresentation. dacă stocați imaginea ca JPEGRepresentation, imaginea nu se va roti!
adăugat autor Mubasher, sursa
iOS dezvoltatori, România — Moldova
iOS dezvoltatori, România — Moldova
21 participanți

Parteneri: ciupacabra.com, @php_ro, @js_ro, @node_ro, @seo_ro Android: @ro_android