2017-10-20 16 views
5

मैं फोटो कैप्चर को संभालने के लिए AVFoundation की प्रतिनिधि विधि को कॉल कर रहा हूं, लेकिन मुझे AVCapturePhoto को परिवर्तित करने में कठिनाई हो रही है जो इसे सही अभिविन्यास के साथ एक UIImage में उत्पन्न करती है। यद्यपि नीचे दिया गया दिनचर्या सफल है, लेकिन मुझे हमेशा एक सही उन्मुख UIImage (UIImage.imageOrientation = 3) मिलता है। UIImage (डेटा: छवि) का उपयोग करते समय मुझे पहले अभिविन्यास प्रदान करने का कोई तरीका नहीं है और पहले फोटो.cgImageReresentation() का उपयोग करने का प्रयास कर रहा है। TakeRetainedValue() भी मदद नहीं करता है। कृपया सहायता करें।सही अभिविन्यास के साथ AVCapturePhoto से UIImage कैसे उत्पन्न करें?

छवि अभिविन्यास यहां महत्वपूर्ण है क्योंकि परिणामी छवि को विजन फ्रेमवर्क वर्कफ़्लो को खिलाया जा रहा है।

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { 
    // capture image finished 
    print("Image captured.") 
    if let imageData = photo.fileDataRepresentation() { 
     if let uiImage = UIImage(data: imageData){ 
      // do stuff to UIImage 
     } 
    } 
} 

अद्यतन 1: पढ़ना एप्पल के Photo Capture Programming Guide (iOS11 के लिए पुराने हो चुके), मैं एक बात लगता है मैं गलत कर रहा था क्या जादू कर दिया: (

  1. हर कब्जा कॉल पर self.capturePhotoOutput .capturePhoto) किसी को फोटोऑटपुट ऑब्जेक्ट के साथ कनेक्शन सेट करना होगा और तस्वीर लेने के समय डिवाइस के अभिविन्यास से मेल खाने के लिए अपना अभिविन्यास अपडेट करना होगा। ऐसा करने के लिए, मैंने UIDeviceOrientation का एक विस्तार बनाया और इसे स्नैपफोटो() फ़ंक्शन पर इस्तेमाल किया जिसे मैंने कैप्चर रूटीन कॉल करने के लिए बनाया था और फ़िनिशप्रोसेसिंग फोटो प्रतिनिधि विधि को निष्पादित करने की प्रतीक्षा की थी। मैंने कोडों का स्नैपशॉट जोड़ा है क्योंकि कोड नमूना डिलीमीटर यहां उन्हें सही तरीके से प्रदर्शित नहीं कर रहे हैं। enter image description here enter image description here

अद्यतन 2 लिंक GitHub पर पूर्ण परियोजना के लिए: https://github.com/agu3rra/Out-Loud

+0

दिलचस्प है, और संभवतः एक [बग की रिपोर्ट दर्ज करने के लिए] (http://bugreport.apple.com)। क्या यह अभिविन्यास को अनदेखा कर रहा है यदि आप उस डेटा को फ़ाइल में लिखते हैं और फ़ाइल-आधारित 'UIImage' प्रारंभकर्ता का उपयोग करते हैं? – rickster

+0

स्नैपफोटो() दिनचर्या (अद्यतन 1) पर कनेक्शन कॉल जोड़ने के बाद, यह अब अभिविन्यास को अनदेखा नहीं कर रहा है, लेकिन यह मुझे UIImage I बनाने पर गलत अभिविन्यास मान वापस दे रहा है। आपके अभिविन्यास विस्तार के बारे में –

+1

। ऐप्पल ने एवीकैम अपडेट किया है। एक समान एक्सटेंशन है। 'एक्सटेंशन UIDeviceOrientation { var videoOrientation: AVCaptureVideoOrientation? { स्विच स्वयं { मामले .portrait: वापसी .portrait मामले .portraitUpsideDown: वापसी .portraitUpsideDown मामले .landscapeLeft: वापसी .landscapeRight मामले .landscapeRight: वापसी .landscapeLeft डिफ़ॉल्ट: वापसी शून्य} } } ' –

उत्तर

1

AVCapturePhoto अंदर मैं बहुत यकीन है कि आप की भी CGImageProperties नामक एक metadata वस्तु मिल जाएगा हूँ।
इसके अंदर आपको ओरिएंटेशन के लिए EXIF ​​शब्दकोश मिलेगा अगला चरण केवल उन्मुखीकरण लेने और उसके अनुसार एक छवि बनाने के लिए है।
मुझे AVCapturePhotoOutput का उपयोग करने में अनुभव नहीं हैं लेकिन मेरे पास पुराने तरीके से कुछ उपयोग कर रहे हैं।
ध्यान दें कि EXII शब्दकोश UIImageOrientation में अलग-अलग मैप किया गया है।
यहां एक article है जो मैंने बहुत समय पहले लिखा था, लेकिन मुख्य सिद्धांत अभी भी मान्य है।
यह question आपको कुछ कार्यान्वयन के लिए इंगित करेगा, यह भी बहुत पुराना है, मुझे पूरा यकीन है कि नवीनतम संस्करण में उन्होंने आसान एपीआई जारी की है, लेकिन यह आपको अभी भी इस मुद्दे को लेने में मार्गदर्शन करेगा।

2

अंतिम अद्यतन: मैं अनुप्रयोग के साथ कुछ प्रयोग भाग गया और निम्नलिखित निष्कर्ष के लिए आया था:

  1. kCGImagePropertyOrientation अपने आवेदन और इसके अंदर कब्जा कर लिया छवि के उन्मुखीकरण को प्रभावित प्रतीत नहीं होता है केवल यदि आप कैप्चरफोटो विधि को कॉल करने वाले हैं, तो हर बार जब आप अपना फोटो आउटपुट कनेक्शन अपडेट करते हैं तो डिवाइस अभिविन्यास के साथ भिन्न होता है।तो:

    समारोह snapPhoto() { // तैयार करने और छवि पर कब्जा दिनचर्या

    // if I leave the next 4 lines commented, the intented orientation of the image on display will be 6 (right top) - kCGImagePropertyOrientation 
    let deviceOrientation = UIDevice.current.orientation // retrieve current orientation from the device 
    guard let photoOutputConnection = capturePhotoOutput.connection(with: AVMediaType.video) else {fatalError("Unable to establish input>output connection")}// setup a connection that manages input > output 
    guard let videoOrientation = deviceOrientation.getAVCaptureVideoOrientationFromDevice() else {return} 
    photoOutputConnection.videoOrientation = videoOrientation // update photo's output connection to match device's orientation 
    
    let photoSettings = AVCapturePhotoSettings() 
    photoSettings.isAutoStillImageStabilizationEnabled = true 
    photoSettings.isHighResolutionPhotoEnabled = true 
    photoSettings.flashMode = .auto 
    self.capturePhotoOutput.capturePhoto(with: photoSettings, delegate: self) // trigger image capture. It appears to work only if the capture session is running. 
    

    आरंभ}

  2. डिबगर पर उत्पन्न छवियों को देखने के लिए मुझे पता चला है कि वे किस तरह उत्पन्न हो, तो मैं यह आवश्यक रोटेशन (UIImageOrientation) को सीधे प्रदर्शित करने के लिए अनुमान लगा सकता है। दूसरे शब्दों में: UIImageOrientation को अपडेट करना बताता है कि सही दिशा में इसे देखने के लिए छवि को कैसे घुमाया जाना चाहिए। UIImageOrientation { // वापसी CGImagePropertyOrientation आधारित> -

    विस्तार UIDeviceOrientation { समारोह getUIImageOrientationFromDevice(): Which UIImageOrientation to apply according to how the device was at the time of capture

  3. मैं एक नहीं बल्कि unintuitive फार्म के लिए मेरी UIDeviceOrientation एक्सटेंशन को अपडेट करना पड़ा: तो मैं निम्न तालिका के लिए आया था डिवाइस ओरिएंटेशन // इस विस्तारित फ़ंक्शन को यूआईएममेज को प्रदर्शित करने के तरीके के प्रयोग के आधार पर निर्धारित किया गया है। स्विच स्वयं { मामले UIDeviceOrientation.portrait, .faceUp: वापसी UIImageOrientation.right मामले UIDeviceOrientation.portraitUpsideDown, .faceDown: वापसी UIImageOrientation.left मामले UIDeviceOrientation.landscapeLeft: वापसी UIImageOrientation.up // इस आधार उन्मुखीकरण है मामले UIDeviceOrientation .landscapeRight: वापसी UIImageOrientation.down मामले UIDeviceOrientation.unknown: वापसी UIImageOrientation.up } } }

  4. इस तरह मेरा अंतिम प्रतिनिधि विधि अब दिखता है। यह अपेक्षित अभिविन्यास में छवि प्रदर्शित करता है।

    func photoOutput(_ output: AVCapturePhotoOutput, 
               didFinishProcessingPhoto photo: AVCapturePhoto, 
               error: Error?) 
    { 
        // capture image finished 
        print("Image captured.") 
    
        let photoMetadata = photo.metadata 
        // Returns corresponting NSCFNumber. It seems to specify the origin of the image 
        //    print("Metadata orientation: ",photoMetadata["Orientation"]) 
    
        // Returns corresponting NSCFNumber. It seems to specify the origin of the image 
        print("Metadata orientation with key: ",photoMetadata[String(kCGImagePropertyOrientation)] as Any) 
    
        guard let imageData = photo.fileDataRepresentation() else { 
         print("Error while generating image from photo capture data."); 
         self.lastPhoto = nil; self.controller.goToProcessing(); 
         return 
    
        } 
    
        guard let uiImage = UIImage(data: imageData) else { 
         print("Unable to generate UIImage from image data."); 
         self.lastPhoto = nil; self.controller.goToProcessing(); 
         return 
    
        } 
    
        // generate a corresponding CGImage 
        guard let cgImage = uiImage.cgImage else { 
         print("Error generating CGImage");self.lastPhoto=nil;return 
    
        } 
    
        guard let deviceOrientationOnCapture = self.deviceOrientationOnCapture else { 
         print("Error retrieving orientation on capture");self.lastPhoto=nil; 
         return 
    
        } 
    
        self.lastPhoto = UIImage(cgImage: cgImage, scale: 1.0, orientation: deviceOrientationOnCapture.getUIImageOrientationFromDevice()) 
    
        print(self.lastPhoto) 
        print("UIImage generated. Orientation:(self.lastPhoto.imageOrientation.rawValue)") 
        self.controller.goToProcessing() 
    } 
    
    
    func photoOutput(_ output: AVCapturePhotoOutput, 
            willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings) 
            { 
        print("Just about to take a photo.") 
        // get device orientation on capture 
        self.deviceOrientationOnCapture = UIDevice.current.orientation 
        print("Device orientation: \(self.deviceOrientationOnCapture.rawValue)") 
    } 
    
संबंधित मुद्दे