iOS इमेज ओरिएंटेशन में स्ट्रेंज बिहेवियर है


94

पिछले कुछ हफ्तों से मैं ऑब्जेक्टिव-सी में छवियों के साथ काम कर रहा हूं और बहुत सारे अजीब व्यवहार देख रहा हूं। सबसे पहले, कई अन्य लोगों की तरह, मुझे यह समस्या हो रही है कि कैमरे के साथ ली गई छवियां (या किसी और के कैमरे के साथ ली गई हैं और मेरे लिए MMS'd) 90 डिग्री घुमाए गए हैं। मुझे यकीन नहीं था कि दुनिया में ऐसा क्यों हो रहा था (इसलिए मेरा सवाल ) लेकिन मैं एक सस्ते काम के साथ आने में सक्षम था।

मेरा सवाल इस बार ऐसा क्यों हो रहा है ? Apple क्यों घूमती है छवियाँ? जब मैं अपने कैमरे को राइट-अप अप के साथ एक फोटो लेता हूं, जब तक कि मैं ऊपर उल्लिखित अपने कोड को निष्पादित नहीं करता, जब मैं फोटो को सहेजता हूं तो यह घुमाए जाने से बच जाता है। अब, मेरा वर्कअराउंड कुछ दिनों पहले तक ठीक था।

मेरा आवेदन एक छवि के अलग-अलग पिक्सल को संशोधित करता है, विशेष रूप से पीएनजी का अल्फा चैनल (इसलिए कोई भी जेपीईजी रूपांतरण मेरे परिदृश्य के लिए खिड़की से बाहर फेंक दिया जाता है)। कुछ दिन पहले मैंने देखा कि भले ही मेरे वर्कअराउंड कोड की बदौलत मेरे ऐप में इमेज ठीक से दिखाई दे रही हो, जब मेरा अल्गोरिदम इमेज के अलग-अलग पिक्सल को मॉडिफाई करता है, तो उसे लगता है कि इमेज रोटेट हो गई है। इसलिए छवि के शीर्ष पर पिक्सेल को संशोधित करने के बजाय, यह छवि के किनारे पिक्सेल को संशोधित करता है (क्योंकि यह सोचता है कि इसे घुमाया जाना चाहिए)! मैं यह पता नहीं लगा सकता कि छवि को स्मृति में कैसे घुमाया जाए - आदर्श रूप से मैं उस imageOrientationध्वज को सभी को एक साथ मिटा देना पसंद करूंगा ।

यहाँ कुछ और है जो मुझे भी चकित कर रहा है ... जब मैं फोटो लेता हूं, तो imageOrientation3 पर सेट होता है। मेरा वर्कअराउंड कोड यह महसूस करने के लिए काफी स्मार्ट है और इसे फ्लिप करें ताकि उपयोगकर्ता कभी नोटिस न करे। इसके अतिरिक्त, लाइब्रेरी में छवि को सहेजने के लिए मेरा कोड यह महसूस करता है, इसे फ़्लिप करता है, फिर इसे सहेजता है ताकि यह कैमरा रोल में ठीक से दिखाई दे।

ऐसा कोड दिखता है:

NSData* pngdata = UIImagePNGRepresentation (self.workingImage); //PNG wrap 
UIImage* img = [self rotateImageAppropriately:[UIImage imageWithData:pngdata]];   
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);

जब मैं इस नई सहेजी गई छवि को अपने ऐप में लोड करता हूं, तो imageOrientation0 है - बिल्कुल वही जो मैं देखना चाहता हूं, और मेरे रोटेशन वर्कअराउंड को भी चलाने की आवश्यकता नहीं है (ध्यान दें: जब कैमरा से ली गई छवियों के विपरीत इंटरनेट से छवियों को लोड करना हो , imageOrientationहमेशा 0 होता है, जिसके परिणामस्वरूप पूर्ण व्यवहार होता है)। किसी कारण से, मेरा कोड इस imageOrientationध्वज को मिटा देता है । मैं बस उस कोड को चोरी करने की उम्मीद कर रहा था और जैसे ही उपयोगकर्ता एक फोटो लेता है और इसे ऐप में जोड़ दिया है, मेरी छवि को मिटा देने के लिए इसका उपयोग करता है, लेकिन यह काम नहीं करता है। के UIImageWriteToSavedPhotosAlbumसाथ कुछ खास करता है imageOrientation?

क्या इस समस्या के लिए सबसे अच्छा समाधान यह होगा कि imageOrientationजैसे ही उपयोगकर्ता चित्र ले रहा है, वैसे ही उड़ जाएं । मुझे लगता है Apple एक कारण के लिए रोटेशन व्यवहार किया है, है ना? कुछ लोगों ने सुझाव दिया कि यह एक Apple दोष है।

(... यदि आप अभी तक खोए नहीं हैं ... नोट 2: जब मैं एक क्षैतिज तस्वीर लेता हूं, तो सब कुछ पूरी तरह से काम करने लगता है, जैसे इंटरनेट से ली गई तस्वीरें)

संपादित करें:

यहाँ कुछ चित्र और परिदृश्य वास्तव में दिखते हैं। अब तक की टिप्पणियों के आधार पर, ऐसा लगता है कि यह अजीब व्यवहार सिर्फ एक iPhone व्यवहार से अधिक है, जो मुझे लगता है कि अच्छा है।

यह उस तस्वीर का चित्र है जिसे मैंने अपने फोन के साथ लिया था (उचित अभिविन्यास पर ध्यान दें), यह बिल्कुल वैसा ही प्रतीत होता है जैसा कि मैंने अपने फोन पर किया था जब मैंने फोटो खींचा था:

IPhone पर ली गई वास्तविक तस्वीर

जीमेल में छवि अपने आप को ईमेल करने के बाद क्या दिखती है (जैसा जीमेल इसे ठीक से हैंडल करता है):

फोटो जैसा कि जीमेल में दिखाई देता है

यहाँ वही है जो छवि खिड़कियों में एक थंबनेल के रूप में दिखती है (ऐसा नहीं लगता कि इसे ठीक से संभाला गया है):

विंडोज थंबनेल

और यहां विंडोज फोटो व्यूअर के साथ खोले जाने पर वास्तविक चित्र जैसा दिखता है (अभी भी ठीक से नहीं संभाला गया है):

विंडोज फोटो दर्शक संस्करण

इस सवाल पर सभी टिप्पणियों के बाद, यहाँ मैं क्या सोच रहा हूँ ... iPhone एक छवि लेता है, और कहता है "इसे ठीक से प्रदर्शित करने के लिए, इसे 90 डिग्री घुमाया जाना चाहिए"। यह जानकारी EXIF ​​डेटा में होगी। (यह सीधे ऊर्ध्वाधर के लिए डिफ़ॉल्ट होने के बजाय, 90 डिग्री घूमने की आवश्यकता क्यों है, मुझे नहीं पता)। यहां से, Gmail उस EXIF ​​डेटा को पढ़ने और विश्लेषण करने के लिए काफी स्मार्ट है, और इसे ठीक से प्रदर्शित करता है। हालाँकि, Windows EXIF ​​डेटा पढ़ने के लिए पर्याप्त स्मार्ट नहीं है, और इसलिए छवि को अनुचित तरीके से प्रदर्शित करता है । क्या मेरी धारणाएँ सही हैं?


दिलचस्प ... अगर यह सच है, तो छवियों को सही कोण पर सेट क्यों किया जा रहा है? मुझे पता है कि यह एक iPhone दोष नहीं है, क्योंकि मैंने इसी तरह के व्यवहार को देखा है जब एक दोस्त (ब्लैकबेरी के साथ) एक छवि और एमएमएस मेरे पास ले जाता है।
बोकेम

देखें कि आपका कैमरा मेटाडाटा को 90 डिग्री पर घुमाने के लिए लिखता है, कुछ ओएस ने पढ़ा कि मेटाडेटा और बाकी नहीं।
हर्षित

बहुत अच्छा पढ़ा (नीचे @ हेडली का जवाब देखें - एक टिप्पणी में इस्तेमाल किया गया था)। तो मेरे ऐप को स्पष्ट रूप से उन चित्रों को संभालने के लिए पर्याप्त स्मार्ट होने की आवश्यकता है जिनमें EXIF ​​डेटा, साथ ही ऐसी छवियां शामिल हैं जो इसमें शामिल नहीं हैं ... मुझे अभी भी समझ में नहीं आया है कि जब मैं एक फोटो राइट-अप अप, ओरिएंटेशन फ्लैग लेता हूं यह 90 डिग्री घुमाया जाना चाहिए?
बोकेम

आप अपने फोटो मोड को पोर्ट्रेट पर सेट करते हैं और आप अपने कैमरे को सही कोण पर नहीं घुमा रहे हैं या लैंडस्केप मोड सेट है और कैमरा ने सही कोण वाली स्थिति में छवि को कैप्चर किया है, सेंसर स्वचालित रूप से ओरिएंटेशन को उचित सेट करेगा। इसे देखें
हर्षित

1
समाधान शायद सबसे अधिक है, आपके ऐप को मेटा डेटा पढ़ने और छवि को घुमाने और / या आवश्यकता के अनुसार मेटाडेटा को संशोधित करने की आवश्यकता है।
हर्षित

जवाबों:


50

मैंने इस पर R & D किया और खोज की, हर छवि फ़ाइल में मेटाडेटा गुण है। यदि मेटाडेटा छवि के अभिविन्यास को निर्दिष्ट करता है जिसे आमतौर पर अन्य ओएस लेकिन मैक द्वारा अनदेखा किया जाता है। ली गई अधिकांश छवियां उनके मेटा डेटा गुण को समकोण पर सेट कर रही हैं। इसलिए मैक इसे 90 डिग्री घुमाए हुए तरीके से दिखाता है। आप विंडोज़ ओएस में उचित तरीके से एक ही छवि देख सकते हैं।

अधिक विवरण के लिए इस उत्तर को पढ़ें http://graphicssoft.about.com/od/digitalphotography/f/sideways-pictures.htm

यहां अपनी छवि के exif को पढ़ने की कोशिश करें http://www.exifviewer.org/ , या http://regex.info/exif.cgi , या http://www.addictivetips.com/internet-tips/view-complete-exif -metadata-जानकारी-ऑफ-द-किसी भी jpeg छवि ऑनलाइन /


1
वाह! मुझे नहीं पता था कि EXIF ​​डेटा में कुछ जानकारी थी! regex.info/exif.cgi एक अविश्वसनीय साइट है! मैं निश्चित रूप से इस साइट पर आज रात छवियों के साथ खेल रहा हूँ। मुझे हर परिदृश्य का परीक्षण करना होगा, छवियां सीधे ऊपर ले जाएंगी, इंटरनेट से ली गई छवियां, घुमाए गए चित्र आदि, धन्यवाद एक टन!
बोकेम

पहला एक्सिफ़ लिंक अब टूट गया है, और दूसरा को exif.regex.info/exif.cgi में अपडेट किया गया है मैंने उत्तर को संपादित करने की कोशिश की लेकिन @ cj-dennis ने इसे किसी कारण से अस्वीकार कर दिया।
रयान

55

कैमरा से छवि प्राप्त करने पर मुझे यही समस्या थी, मैंने इसे ठीक करने के लिए निम्न कोड डाला .. यहाँ से विधि जोड़ा गया ।AndRotateImage

- (void) imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)imageInfo {
            // Images from the camera are always in landscape, so rotate
                    UIImage *image = [self scaleAndRotateImage: [imageInfo objectForKey:UIImagePickerControllerOriginalImage]];
    //then save the image to photo gallery or wherever  
        }


- (UIImage *)scaleAndRotateImage:(UIImage *) image {
    int kMaxResolution = 320;

    CGImageRef imgRef = image.CGImage;

    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);


    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    if (width > kMaxResolution || height > kMaxResolution) {
        CGFloat ratio = width/height;
        if (ratio > 1) {
            bounds.size.width = kMaxResolution;
            bounds.size.height = bounds.size.width / ratio;
        }
        else {
            bounds.size.height = kMaxResolution;
            bounds.size.width = bounds.size.height * ratio;
        }
    }

    CGFloat scaleRatio = bounds.size.width / width;
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    UIImageOrientation orient = image.imageOrientation;
    switch(orient) {

        case UIImageOrientationUp: //EXIF = 1
            transform = CGAffineTransformIdentity;
            break;

        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;

        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;

        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];

    }

    UIGraphicsBeginImageContext(bounds.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    }
    else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }

    CGContextConcatCTM(context, transform);

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

3
आपका पैमाना क्या है .AndRotateImage कोड कैसा दिखता है? Google करने के बाद, क्या यह यहाँ के समान है? चर्चा
.apple.com

2
वाह ... हाहा! यह बहुत अच्छी तरह से काम किया! मैंने ऊपर अपनी टिप्पणी में कोड का उपयोग किया है। मुझे अपने प्रश्न के दो अद्भुत उत्तर मिले! मुझे लगता है कि इसका मतलब है कि मैंने बहुत बड़ा सवाल पूछा है ... धन्यवाद एक टन। मेरे पास करने के लिए कुछ गहराई से परीक्षण होगा, लेकिन अभी तक ओरिएंटेशन समस्या लंबवत और क्षैतिज रूप से ली गई तस्वीरों के साथ शानदार काम करती है।
बोकेम

3
मुझे लगता है कि आपकी विधि का एक हिस्सा गायब है, लेकिन वह और लिंक अभी भी मेरे लिए बाकी काम करने के लिए पर्याप्त था और अंत में मेरी छवि को ठीक से काम करने का दृश्य मिलता है, इसलिए धन्यवाद :)
विक स्मिथ

मुझे खुशी है कि इसने मदद की .. :)
दिलीप राजकुमार

क्या यह कोड ब्लॉक करता है कि मूल छवि कैसी दिखती है, लेकिन अप करने के लिए अभिविन्यास को बदल दें?
जूनो गु

18

दिलीप के उत्कृष्ट उत्तर की त्वरित प्रतिलिपि / पेस्ट स्विफ्ट अनुवाद ।

import Darwin

class func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {

    let imgRef = imageSource.CGImage;

    let width = CGFloat(CGImageGetWidth(imgRef));
    let height = CGFloat(CGImageGetHeight(imgRef));

    var bounds = CGRectMake(0, 0, width, height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransformIdentity
    let orient = imageSource.imageOrientation
    let imageSize = CGSizeMake(CGFloat(CGImageGetWidth(imgRef)), CGFloat(CGImageGetHeight(imgRef)))


    switch(imageSource.imageOrientation) {
    case .Up :
        transform = CGAffineTransformIdentity

    case .UpMirrored :
        transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);

    case .Down :
        transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI));

    case .DownMirrored :
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
        transform = CGAffineTransformScale(transform, 1.0, -1.0);

    case .Left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
        transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);

    case .LeftMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
        transform = CGAffineTransformScale(transform, -1.0, 1.0);
        transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);

    case .Right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);

    case .RightMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransformMakeScale(-1.0, 1.0);
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);

    default : ()
    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()

    if orient == .Right || orient == .Left {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    } else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }

    CGContextConcatCTM(context, transform);
    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

1
धन्यवाद, लेकिन "अनुपात = चौड़ाई / ऊंचाई क्या है?" के लिए उपयोग कर रहे हैं? मैं उस {}
पेंगज़ी झोउ

18

मेरा सवाल इस बार ऐसा क्यों हो रहा है? Apple क्यों घूमती है छवियाँ?

इसका उत्तर बहुत सरल है। Apple छवि को घुमा नहीं रहा है। बस यहीं से भ्रम होता है।

सीसीडी कैमरा घूमता नहीं है, इसलिए यह हमेशा परिदृश्य मोड में फोटो ले रहा है।

Apple ने एक बहुत ही स्मार्ट काम किया - छवि को घुमाने के लिए हर समय खर्च करने के बजाय - डेटा के मेगाबाइट को फेरबदल करने के लिए - बस इसे चित्र कैसे लिया गया, इसके साथ टैग करें।

OpenGL बहुत आसानी से अनुवाद करता है - इसलिए DATA कभी भी फेरबदल नहीं करता - बस HOW ITS DRAWN।

इसलिए ओरिएंटेशन मेटा डेटा।

यह एक समस्या बन जाती है यदि आप फसल करना चाहते हैं, आकार बदल सकते हैं आदि - लेकिन एक बार जब आप जानते हैं कि क्या हो रहा है, तो आप बस अपने मैट्रिक्स को परिभाषित करते हैं और सब कुछ काम करता है।


1
इस स्पष्टीकरण के लिए धन्यवाद। एक बार जब आप इसके बारे में सोचते हैं, तो सामान्य ज्ञान, लेकिन किसी भी अन्य परिणाम ने इसे नहीं समझाया।
डाकिने83

16

दिलीप के जवाब की सुरक्षा जांच के साथ स्विफ्ट 4 संस्करण ।

public static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat = 320) -> UIImage? {

    guard let imgRef = imageSource.cgImage else {
        return nil
    }

    let width = CGFloat(imgRef.width)
    let height = CGFloat(imgRef.height)

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: CGFloat(imgRef.width), height: CGFloat(imgRef.height))

    switch(imageSource.imageOrientation) {
    case .up:
        transform = .identity
    case .upMirrored:
        transform = CGAffineTransform
            .init(translationX: imageSize.width, y: 0)
            .scaledBy(x: -1.0, y: 1.0)
    case .down:
        transform = CGAffineTransform
            .init(translationX: imageSize.width, y: imageSize.height)
            .rotated(by: CGFloat.pi)
    case .downMirrored:
        transform = CGAffineTransform
            .init(translationX: 0, y: imageSize.height)
            .scaledBy(x: 1.0, y: -1.0)
    case .left:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: 0, y: imageSize.width)
            .rotated(by: 3.0 * CGFloat.pi / 2.0)
    case .leftMirrored:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: imageSize.height, y: imageSize.width)
            .scaledBy(x: -1.0, y: 1.0)
            .rotated(by: 3.0 * CGFloat.pi / 2.0)
    case .right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(translationX: imageSize.height, y: 0)
            .rotated(by: CGFloat.pi / 2.0)
    case .rightMirrored:
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width;
        bounds.size.width = storedHeight;
        transform = CGAffineTransform
            .init(scaleX: -1.0, y: 1.0)
            .rotated(by: CGFloat.pi / 2.0)
    }

    UIGraphicsBeginImageContext(bounds.size)
    if let context = UIGraphicsGetCurrentContext() {
        if orient == .right || orient == .left {
            context.scaleBy(x: -scaleRatio, y: scaleRatio)
            context.translateBy(x: -height, y: 0)
        } else {
            context.scaleBy(x: scaleRatio, y: -scaleRatio)
            context.translateBy(x: 0, y: -height)
        }

        context.concatenate(transform)
        context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))
    }

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageCopy
}

आप (bounds.size.height, bounds.size.width) = (bounds.size.width, bounds.size.height)स्टोरेज के रूप में वेरिएबल बनाए बिना भी कर सकते हैं ।
अल्मास सपरगली

मुझे कभी-कभी समस्या होती थी, कि छवि के निचले भाग में स्केलिंग के बाद एक सफेद रेखा दिखाई देती थी। ऐसा इसलिए है क्योंकि सीजीफ्लोट पर्याप्त सटीक नहीं है। मैंने इसके साथ bounds.size.height.round()औरbounds.size.width.round()
ndreisg

13

IPhone / iPad द्वारा उत्पन्न किसी भी छवि को वास्तविक अभिविन्यास निर्दिष्ट करते हुए EXIF ​​ओरिएंटेशन टैग (Exif.Image.Orientation) के साथ लैंडस्केप लेफ्ट के रूप में सहेजा जाता है।

इसके निम्न मूल्य हैं: 1: लैंडस्केप लेफ्ट 6: पोर्ट्रेट नॉर्मल 3: लैंडस्केप राइट 4: पोर्ट्रेट अपसाइड डाउन

IOS में, EXIF ​​जानकारी ठीक से पढ़ी जाती है और छवियों को उसी तरीके से प्रदर्शित किया जाता है जिस तरह से लिया गया था। लेकिन विंडोज में, EXIF ​​जानकारी का उपयोग नहीं किया जाता है।

यदि आप GIMP में इनमें से किसी एक चित्र को खोलते हैं, तो यह कहेगा कि चित्र में रोटेशन की जानकारी है।


8

Xamarin का उपयोग करने वाले किसी और के लिए, यहां दिलीप के शानदार उत्तर का C # अनुवाद है , और स्विफ्ट अनुवाद के लिए थेटसन का धन्यवाद ।

public static UIImage RotateCameraImageToProperOrientation(UIImage imageSource, nfloat maxResolution) {

    var imgRef = imageSource.CGImage;

    var width = (nfloat)imgRef.Width;
    var height = (nfloat)imgRef.Height;

    var bounds = new CGRect(0, 0, width, height);

    nfloat scaleRatio = 1;

    if (width > maxResolution || height > maxResolution) 
    {
        scaleRatio = (nfloat)Math.Min(maxResolution / bounds.Width, maxResolution / bounds.Height);
        bounds.Height = bounds.Height * scaleRatio;
        bounds.Width = bounds.Width * scaleRatio;
    }

    var transform = CGAffineTransform.MakeIdentity();
    var orient = imageSource.Orientation;
    var imageSize = new CGSize(imgRef.Width, imgRef.Height);
    nfloat storedHeight;

    switch(imageSource.Orientation) {
        case UIImageOrientation.Up:
            transform = CGAffineTransform.MakeIdentity();
            break;

        case UIImageOrientation.UpMirrored :
            transform = CGAffineTransform.MakeTranslation(imageSize.Width, 0.0f);
            transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
            break;

        case UIImageOrientation.Down :
            transform = CGAffineTransform.MakeTranslation(imageSize.Width, imageSize.Height);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI);
            break;

        case UIImageOrientation.DownMirrored :
            transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Height);
            transform = CGAffineTransform.Scale(transform, 1.0f, -1.0f);
            break;

        case UIImageOrientation.Left:
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(0.0f, imageSize.Width);
            transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.LeftMirrored :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(imageSize.Height, imageSize.Width);
            transform = CGAffineTransform.Scale(transform, -1.0f, 1.0f);
            transform = CGAffineTransform.Rotate(transform, 3.0f * (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.Right :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeTranslation(imageSize.Height, 0.0f);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
            break;

        case UIImageOrientation.RightMirrored :
            storedHeight = bounds.Height;
            bounds.Height = bounds.Width;
            bounds.Width = storedHeight;
            transform = CGAffineTransform.MakeScale(-1.0f, 1.0f);
            transform = CGAffineTransform.Rotate(transform, (nfloat)Math.PI / 2.0f);
            break;

        default :
            break;
    }

    UIGraphics.BeginImageContext(bounds.Size);
    var context = UIGraphics.GetCurrentContext();

    if (orient == UIImageOrientation.Right || orient == UIImageOrientation.Left) {
        context.ScaleCTM(-scaleRatio, scaleRatio);
        context.TranslateCTM(-height, 0);
    } else {
        context.ScaleCTM(scaleRatio, -scaleRatio);
        context.TranslateCTM(0, -height);
    }

    context.ConcatCTM(transform);
    context.DrawImage(new CGRect(0, 0, width, height), imgRef);

    var imageCopy = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();

    return imageCopy;
}

इससे कई घंटे खेलने के बाद मेरे मुद्दे को सुलझाने में मदद मिली है! अविश्वसनीय है कि Xamarin के पास इसके लिए कुछ अंतर्निहित समर्थन नहीं है क्योंकि यह अब एक Microsoft उत्पाद है।
सामी। सी

4

मुझे इस सवाल का पता चला क्योंकि मुझे एक समान समस्या थी, लेकिन स्विफ्ट का उपयोग करना। बस उस उत्तर से लिंक करना चाहता था जो मेरे लिए किसी अन्य स्विफ्ट डेवलपर्स के लिए काम करता था: https://stackoverflow.com/a/26676578/3904581

यहाँ एक स्विफ्ट स्निपेट है जो समस्या को कुशलता से ठीक करता है:

let orientedImage = UIImage(CGImage: initialImage.CGImage, scale: 1, orientation: initialImage.imageOrientation)!

सुपर सिंपल है। कोड की एक पंक्ति। समस्या सुलझ गयी।


यह मेरे लिए काम नहीं करता था, मैंने इस समाधान का उपयोग किया: stackoverflow.com/a/27775741/945247
Leon

0

मुझे पता है कि आपकी समस्या क्या है। आप UIImagePicker का उपयोग कर रहे हैं, जो हर मायने में अजीब है। मैं आपको सुझाव दूंगा कि आप कैमरा के लिए AVFoundation का उपयोग करें जो कि उन्मुखीकरण के साथ-साथ गुणवत्ता में भी लचीलापन देता है। AVCaptureSession का उपयोग करें। आप यहां पर कोड प्राप्त कर सकते हैं AVFoundation का उपयोग करके फ़ोटो एल्बम में सहेजे गए फ़ोटो कैसे बचाएं?


0

स्विफ्ट 3 के लिए तुरंत रिफ्लेक्ट किया गया (क्या कोई इसका परीक्षण कर सकता है और इसकी पुष्टि कर सकता है कि सब कुछ ठीक है?)

static func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage

    let width = CGFloat(imgRef!.width)
    let height = CGFloat(imgRef!.height)

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if width > maxResolution || height > maxResolution {

        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: imgRef!.width, height: imgRef!.height)

    switch imageSource.imageOrientation {
    case .up :
        transform = CGAffineTransform.identity

    case .upMirrored :
        transform = CGAffineTransform(translationX: imageSize.width, y: 0)
        transform = transform.scaledBy(x: -1, y: 1)

    case .down :
        transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height)
        transform = transform.rotated(by: CGFloat.pi)

    case .downMirrored :
        transform = CGAffineTransform(translationX: 0, y: imageSize.height)
        transform = transform.scaledBy(x: 1, y: -1)

    case .left :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: 0, y: imageSize.width)
        transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0)

    case .leftMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width)
        transform = transform.scaledBy(x: -1, y: 1)
        transform = transform.rotated(by: 3.0 * CGFloat.pi / 2.0)

    case .right :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(translationX: imageSize.height, y: 0)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    case .rightMirrored :
        let storedHeight = bounds.size.height
        bounds.size.height = bounds.size.width
        bounds.size.width = storedHeight
        transform = CGAffineTransform(scaleX: -1, y: 1)
        transform = transform.rotated(by: CGFloat.pi / 2.0)

    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()

    if orient == .right || orient == .left {

        context!.scaleBy(x: -scaleRatio, y: scaleRatio)
        context!.translateBy(x: -height, y: 0)
    } else {
        context!.scaleBy(x: scaleRatio, y: -scaleRatio)
        context!.translateBy(x: 0, y: -height)
    }

    context!.concatenate(transform)
    context!.draw(imgRef!, in: CGRect(x: 0, y: 0, width: width, height: height))

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return imageCopy!
}

0

यहां दिलीप के भयानक जवाब का स्विफ्ट 3 संस्करण है

func rotateCameraImageToProperOrientation(imageSource : UIImage, maxResolution : CGFloat) -> UIImage {
    let imgRef = imageSource.cgImage!;

    let width = CGFloat(imgRef.width);
    let height = CGFloat(imgRef.height);

    var bounds = CGRect(x: 0, y: 0, width: width, height: height)

    var scaleRatio : CGFloat = 1
    if (width > maxResolution || height > maxResolution) {
        scaleRatio = min(maxResolution / bounds.size.width, maxResolution / bounds.size.height)
        bounds.size.height = bounds.size.height * scaleRatio
        bounds.size.width = bounds.size.width * scaleRatio
    }

    var transform = CGAffineTransform.identity
    let orient = imageSource.imageOrientation
    let imageSize = CGSize(width: width, height: height)


    switch(imageSource.imageOrientation) {
        case .up :
            transform = CGAffineTransform.identity

        case .upMirrored :
            transform = CGAffineTransform(translationX: imageSize.width, y: 0.0);
            transform = transform.scaledBy(x: -1, y: 1);

        case .down :
            transform = CGAffineTransform(translationX: imageSize.width, y: imageSize.height);
            transform = transform.rotated(by: CGFloat(Double.pi));

        case .downMirrored :
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.height);
            transform = transform.scaledBy(x: 1, y: -1);

        case .left :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: 0.0, y: imageSize.width);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .leftMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: imageSize.width);
            transform = transform.scaledBy(x: -1, y: 1);
            transform = transform.rotated(by: 3.0 * CGFloat(Double.pi) / 2.0);

        case .right :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(translationX: imageSize.height, y: 0.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);

        case .rightMirrored :
            let storedHeight = bounds.size.height
            bounds.size.height = bounds.size.width;
            bounds.size.width = storedHeight;
            transform = CGAffineTransform(scaleX: -1.0, y: 1.0);
            transform = transform.rotated(by: CGFloat(Double.pi) / 2.0);
    }

    UIGraphicsBeginImageContext(bounds.size)
    let context = UIGraphicsGetCurrentContext()!

    if orient == .right || orient == .left {
        context.scaleBy(x: -scaleRatio, y: scaleRatio);
        context.translateBy(x: -height, y: 0);
    } else {
        context.scaleBy(x: scaleRatio, y: -scaleRatio);
        context.translateBy(x: 0, y: -height);
    }

    context.concatenate(transform);
    context.draw(imgRef, in: CGRect(x: 0, y: 0, width: width, height: height))

    let imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy!;
}

-3

छवि प्रारूप को .jpeg में बदलने का प्रयास करें। इसने मेरे लिए काम किया

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.